3
3
namespace PHPStan \Type \Doctrine \QueryBuilder ;
4
4
5
5
use PhpParser \Node ;
6
+ use PhpParser \Node \Expr \MethodCall ;
7
+ use PhpParser \Node \Identifier ;
6
8
use PhpParser \Node \Stmt ;
7
9
use PhpParser \Node \Stmt \Class_ ;
8
10
use PhpParser \Node \Stmt \ClassMethod ;
15
17
use PHPStan \Analyser \ScopeFactory ;
16
18
use PHPStan \DependencyInjection \Container ;
17
19
use PHPStan \Parser \Parser ;
18
- use PHPStan \Reflection \MethodReflection ;
20
+ use PHPStan \Reflection \ReflectionProvider ;
19
21
use PHPStan \Type \Generic \TemplateTypeMap ;
20
22
use PHPStan \Type \IntersectionType ;
21
23
use PHPStan \Type \Type ;
22
24
use PHPStan \Type \TypeTraverser ;
23
25
use PHPStan \Type \UnionType ;
26
+ use function count ;
24
27
use function is_array ;
25
28
26
29
class OtherMethodQueryBuilderParser
@@ -29,28 +32,61 @@ class OtherMethodQueryBuilderParser
29
32
/** @var bool */
30
33
private $ descendIntoOtherMethods ;
31
34
35
+ /** @var ReflectionProvider */
36
+ private $ reflectionProvider ;
37
+
32
38
/** @var Parser */
33
39
private $ parser ;
34
40
35
41
/** @var Container */
36
42
private $ container ;
37
43
38
- public function __construct (bool $ descendIntoOtherMethods , Parser $ parser , Container $ container )
44
+ public function __construct (bool $ descendIntoOtherMethods , ReflectionProvider $ reflectionProvider , Parser $ parser , Container $ container )
39
45
{
40
46
$ this ->descendIntoOtherMethods = $ descendIntoOtherMethods ;
47
+ $ this ->reflectionProvider = $ reflectionProvider ;
41
48
$ this ->parser = $ parser ;
42
49
$ this ->container = $ container ;
43
50
}
44
51
45
52
/**
46
- * @return list< QueryBuilderType>
53
+ * @return QueryBuilderType[]
47
54
*/
48
- public function findQueryBuilderTypesInCalledMethod (Scope $ scope , MethodReflection $ methodReflection ): array
55
+ public function getQueryBuilderTypes (Scope $ scope , MethodCall $ methodCall ): array
49
56
{
50
- if (!$ this ->descendIntoOtherMethods ) {
57
+ if (!$ this ->descendIntoOtherMethods || !$ methodCall ->var instanceof MethodCall) {
58
+ return [];
59
+ }
60
+
61
+ return $ this ->findQueryBuilderTypesInCalledMethod ($ scope , $ methodCall ->var );
62
+ }
63
+ /**
64
+ * @return QueryBuilderType[]
65
+ */
66
+ private function findQueryBuilderTypesInCalledMethod (Scope $ scope , MethodCall $ methodCall ): array
67
+ {
68
+ $ methodCalledOnType = $ scope ->getType ($ methodCall ->var );
69
+ if (!$ methodCall ->name instanceof Identifier) {
70
+ return [];
71
+ }
72
+
73
+ $ methodCalledOnTypeClassNames = $ methodCalledOnType ->getObjectClassNames ();
74
+
75
+ if (count ($ methodCalledOnTypeClassNames ) !== 1 ) {
76
+ return [];
77
+ }
78
+
79
+ if (!$ this ->reflectionProvider ->hasClass ($ methodCalledOnTypeClassNames [0 ])) {
80
+ return [];
81
+ }
82
+
83
+ $ classReflection = $ this ->reflectionProvider ->getClass ($ methodCalledOnTypeClassNames [0 ]);
84
+ $ methodName = $ methodCall ->name ->toString ();
85
+ if (!$ classReflection ->hasNativeMethod ($ methodName )) {
51
86
return [];
52
87
}
53
88
89
+ $ methodReflection = $ classReflection ->getNativeMethod ($ methodName );
54
90
$ fileName = $ methodReflection ->getDeclaringClass ()->getFileName ();
55
91
if ($ fileName === null ) {
56
92
return [];
0 commit comments