5
5
use Doctrine \ORM \EntityRepository ;
6
6
use Doctrine \ORM \QueryBuilder ;
7
7
use PhpParser \Node \Expr ;
8
+ use PhpParser \Node \Expr \CallLike ;
8
9
use PhpParser \Node \Expr \MethodCall ;
10
+ use PhpParser \Node \Expr \StaticCall ;
9
11
use PhpParser \Node \Identifier ;
12
+ use PhpParser \Node \Name ;
10
13
use PHPStan \Analyser \Scope ;
14
+ use PHPStan \Reflection \MethodReflection ;
11
15
use PHPStan \Reflection \ParametersAcceptorSelector ;
12
16
use PHPStan \Type \ExpressionTypeResolverExtension ;
13
17
use PHPStan \Type \ObjectType ;
@@ -30,30 +34,15 @@ public function __construct(
30
34
31
35
public function getType (Expr $ expr , Scope $ scope ): ?Type
32
36
{
33
- if (!$ expr instanceof MethodCall) {
37
+ if (!$ expr instanceof MethodCall && ! $ expr instanceof StaticCall ) {
34
38
return null ;
35
39
}
36
40
37
41
if ($ expr ->isFirstClassCallable ()) {
38
42
return null ;
39
43
}
40
44
41
- if (!$ expr ->name instanceof Identifier) {
42
- return null ;
43
- }
44
-
45
- $ callerType = $ scope ->getType ($ expr ->var );
46
-
47
- foreach ($ callerType ->getObjectClassReflections () as $ callerClassReflection ) {
48
- if ($ callerClassReflection ->is (QueryBuilder::class)) {
49
- return null ; // covered by QueryBuilderMethodDynamicReturnTypeExtension
50
- }
51
- if ($ callerClassReflection ->is (EntityRepository::class) && $ expr ->name ->name === 'createQueryBuilder ' ) {
52
- return null ; // covered by EntityRepositoryCreateQueryBuilderDynamicReturnTypeExtension
53
- }
54
- }
55
-
56
- $ methodReflection = $ scope ->getMethodReflection ($ callerType , $ expr ->name ->name );
45
+ $ methodReflection = $ this ->getMethodReflection ($ expr , $ scope );
57
46
58
47
if ($ methodReflection === null ) {
59
48
return null ;
@@ -67,12 +56,44 @@ public function getType(Expr $expr, Scope $scope): ?Type
67
56
return null ;
68
57
}
69
58
70
- $ queryBuilderTypes = $ this ->otherMethodQueryBuilderParser ->findQueryBuilderTypesInCalledMethod ($ scope , $ expr );
59
+ $ queryBuilderTypes = $ this ->otherMethodQueryBuilderParser ->findQueryBuilderTypesInCalledMethod ($ scope , $ methodReflection );
71
60
if (count ($ queryBuilderTypes ) === 0 ) {
72
61
return null ;
73
62
}
74
63
75
64
return TypeCombinator::union (...$ queryBuilderTypes );
76
65
}
77
66
67
+ /**
68
+ * @param StaticCall|MethodCall $call
69
+ */
70
+ private function getMethodReflection (CallLike $ call , Scope $ scope ): ?MethodReflection
71
+ {
72
+ if (!$ call ->name instanceof Identifier) {
73
+ return null ;
74
+ }
75
+
76
+ if ($ call instanceof MethodCall) {
77
+ $ callerType = $ scope ->getType ($ call ->var );
78
+ } else {
79
+ if (!$ call ->class instanceof Name) {
80
+ return null ;
81
+ }
82
+ $ callerType = $ scope ->resolveTypeByName ($ call ->class );
83
+ }
84
+
85
+ $ methodName = $ call ->name ->name ;
86
+
87
+ foreach ($ callerType ->getObjectClassReflections () as $ callerClassReflection ) {
88
+ if ($ callerClassReflection ->is (QueryBuilder::class)) {
89
+ return null ; // covered by QueryBuilderMethodDynamicReturnTypeExtension
90
+ }
91
+ if ($ callerClassReflection ->is (EntityRepository::class) && $ methodName === 'createQueryBuilder ' ) {
92
+ return null ; // covered by EntityRepositoryCreateQueryBuilderDynamicReturnTypeExtension
93
+ }
94
+ }
95
+
96
+ return $ scope ->getMethodReflection ($ callerType , $ methodName );
97
+ }
98
+
78
99
}
0 commit comments