22
22
use PHPStan \Reflection \ReflectionProvider ;
23
23
use PHPStan \Type \Type ;
24
24
use PHPStan \Type \TypeCombinator ;
25
- use ShipMonk \PHPStan \DeadCode \Helper \DeadCodeHelper ;
25
+ use ShipMonk \PHPStan \DeadCode \Crate \Call ;
26
+ use function array_map ;
26
27
27
28
/**
28
29
* @implements Collector<Node, list<string>>
@@ -33,7 +34,7 @@ class MethodCallCollector implements Collector
33
34
private ReflectionProvider $ reflectionProvider ;
34
35
35
36
/**
36
- * @var list<string >
37
+ * @var list<Call >
37
38
*/
38
39
private array $ callsBuffer = [];
39
40
@@ -82,7 +83,14 @@ public function processNode(
82
83
if (!$ scope ->isInClass () || $ node instanceof ClassMethodsNode) { // @phpstan-ignore-line ignore BC promise
83
84
$ data = $ this ->callsBuffer ;
84
85
$ this ->callsBuffer = [];
85
- return $ data === [] ? null : $ data ; // collect data once per class to save memory & resultCache size
86
+
87
+ // collect data once per class to save memory & resultCache size
88
+ return $ data === []
89
+ ? null
90
+ : array_map (
91
+ static fn (Call $ call ): string => $ call ->toString (),
92
+ $ data ,
93
+ );
86
94
}
87
95
88
96
return null ;
@@ -101,15 +109,18 @@ private function registerMethodCall(
101
109
if ($ methodCall instanceof New_) {
102
110
if ($ methodCall ->class instanceof Expr) {
103
111
$ callerType = $ scope ->getType ($ methodCall ->class );
112
+ $ possibleDescendantCall = true ;
104
113
105
114
} elseif ($ methodCall ->class instanceof Name) {
106
115
$ callerType = $ scope ->resolveTypeByName ($ methodCall ->class );
116
+ $ possibleDescendantCall = $ methodCall ->class ->toString () === 'static ' ;
107
117
108
118
} else {
109
119
return ;
110
120
}
111
121
} else {
112
122
$ callerType = $ scope ->getType ($ methodCall ->var );
123
+ $ possibleDescendantCall = true ;
113
124
}
114
125
115
126
if ($ methodName === null ) {
@@ -118,7 +129,7 @@ private function registerMethodCall(
118
129
119
130
foreach ($ this ->getReflectionsWithMethod ($ callerType , $ methodName ) as $ classWithMethod ) {
120
131
$ className = $ classWithMethod ->getMethod ($ methodName , $ scope )->getDeclaringClass ()->getName ();
121
- $ this ->callsBuffer [] = DeadCodeHelper:: composeMethodKey ($ className , $ methodName );
132
+ $ this ->callsBuffer [] = new Call ($ className , $ methodName, $ possibleDescendantCall );
122
133
}
123
134
}
124
135
@@ -136,8 +147,11 @@ private function registerStaticCall(
136
147
if ($ staticCall ->class instanceof Expr) {
137
148
$ callerType = $ scope ->getType ($ staticCall ->class );
138
149
$ classReflections = $ this ->getReflectionsWithMethod ($ callerType , $ methodName );
150
+ $ possibleDescendantCall = true ;
151
+
139
152
} else {
140
153
$ className = $ scope ->resolveName ($ staticCall ->class );
154
+ $ possibleDescendantCall = $ staticCall ->class ->toString () === 'static ' ;
141
155
142
156
if ($ this ->reflectionProvider ->hasClass ($ className )) {
143
157
$ classReflections = [
@@ -150,7 +164,7 @@ private function registerStaticCall(
150
164
151
165
foreach ($ classReflections as $ classWithMethod ) {
152
166
$ className = $ classWithMethod ->getMethod ($ methodName , $ scope )->getDeclaringClass ()->getName ();
153
- $ this ->callsBuffer [] = DeadCodeHelper:: composeMethodKey ($ className , $ methodName );
167
+ $ this ->callsBuffer [] = new Call ($ className , $ methodName, $ possibleDescendantCall );
154
168
}
155
169
}
156
170
@@ -164,11 +178,15 @@ private function registerArrayCallable(
164
178
$ callableTypeAndNames = $ constantArray ->findTypeAndMethodNames ();
165
179
166
180
foreach ($ callableTypeAndNames as $ typeAndName ) {
181
+ $ caller = $ typeAndName ->getType ();
167
182
$ methodName = $ typeAndName ->getMethod ();
168
183
169
- foreach ($ this ->getReflectionsWithMethod ($ typeAndName ->getType (), $ methodName ) as $ classWithMethod ) {
184
+ // currently always true, see https://github.com/phpstan/phpstan-src/pull/3372
185
+ $ possibleDescendantCall = !$ caller ->isClassStringType ()->yes ();
186
+
187
+ foreach ($ this ->getReflectionsWithMethod ($ caller , $ methodName ) as $ classWithMethod ) {
170
188
$ className = $ classWithMethod ->getMethod ($ methodName , $ scope )->getDeclaringClass ()->getName ();
171
- $ this ->callsBuffer [] = DeadCodeHelper:: composeMethodKey ($ className , $ methodName );
189
+ $ this ->callsBuffer [] = new Call ($ className , $ methodName, $ possibleDescendantCall );
172
190
}
173
191
}
174
192
}
@@ -177,7 +195,7 @@ private function registerArrayCallable(
177
195
178
196
private function registerAttribute (Attribute $ node , Scope $ scope ): void
179
197
{
180
- $ this ->callsBuffer [] = DeadCodeHelper:: composeMethodKey ($ scope ->resolveName ($ node ->name ), '__construct ' );
198
+ $ this ->callsBuffer [] = new Call ($ scope ->resolveName ($ node ->name ), '__construct ' , false );
181
199
}
182
200
183
201
/**
0 commit comments