13
13
use PhpParser \Node \Name ;
14
14
use PHPStan \Analyser \Scope ;
15
15
use PHPStan \Collectors \Collector ;
16
+ use PHPStan \Node \ClassMethodsNode ;
16
17
use PHPStan \Node \MethodCallableNode ;
17
18
use PHPStan \Node \StaticMethodCallableNode ;
18
19
use PHPStan \Reflection \ClassReflection ;
@@ -28,6 +29,11 @@ class MethodCallCollector implements Collector
28
29
29
30
private ReflectionProvider $ reflectionProvider ;
30
31
32
+ /**
33
+ * @var list<string>
34
+ */
35
+ private array $ callsBuffer = [];
36
+
31
37
public function __construct (ReflectionProvider $ reflectionProvider )
32
38
{
33
39
$ this ->reflectionProvider = $ reflectionProvider ;
@@ -47,66 +53,64 @@ public function processNode(
47
53
): ?array
48
54
{
49
55
if ($ node instanceof MethodCallableNode) { // @phpstan-ignore-line ignore BC promise
50
- return $ this ->registerMethodCall ($ node ->getOriginalNode (), $ scope );
56
+ $ this ->registerMethodCall ($ node ->getOriginalNode (), $ scope );
51
57
}
52
58
53
59
if ($ node instanceof StaticMethodCallableNode) { // @phpstan-ignore-line ignore BC promise
54
- return $ this ->registerStaticCall ($ node ->getOriginalNode (), $ scope );
60
+ $ this ->registerStaticCall ($ node ->getOriginalNode (), $ scope );
55
61
}
56
62
57
63
if ($ node instanceof MethodCall || $ node instanceof NullsafeMethodCall) {
58
- return $ this ->registerMethodCall ($ node , $ scope );
64
+ $ this ->registerMethodCall ($ node , $ scope );
59
65
}
60
66
61
67
if ($ node instanceof StaticCall) {
62
- return $ this ->registerStaticCall ($ node , $ scope );
68
+ $ this ->registerStaticCall ($ node , $ scope );
63
69
}
64
70
65
71
if ($ node instanceof FuncCall) {
66
- return $ this ->registerFuncCall ($ node , $ scope );
72
+ $ this ->registerFuncCall ($ node , $ scope );
73
+ }
74
+
75
+ if (!$ scope ->isInClass () || $ node instanceof ClassMethodsNode) { // @phpstan-ignore-line ignore BC promise
76
+ $ data = $ this ->callsBuffer ;
77
+ $ this ->callsBuffer = [];
78
+ return $ data === [] ? null : $ data ; // collect data once per class to save memory & resultCache size
67
79
}
68
80
69
81
return null ;
70
82
}
71
83
72
84
/**
73
85
* @param NullsafeMethodCall|MethodCall $methodCall
74
- * @return list<string>|null
75
86
*/
76
87
private function registerMethodCall (
77
88
CallLike $ methodCall ,
78
89
Scope $ scope
79
- ): ? array
90
+ ): void
80
91
{
81
92
$ methodName = $ this ->getMethodName ($ methodCall );
82
93
$ callerType = $ scope ->getType ($ methodCall ->var );
83
94
84
95
if ($ methodName === null ) {
85
- return null ;
96
+ return ;
86
97
}
87
98
88
- $ result = [];
89
-
90
99
foreach ($ this ->getReflectionsWithMethod ($ callerType , $ methodName ) as $ classWithMethod ) {
91
100
$ className = $ classWithMethod ->getMethod ($ methodName , $ scope )->getDeclaringClass ()->getName ();
92
- $ result [] = DeadCodeHelper::composeMethodKey ($ className , $ methodName );
101
+ $ this -> callsBuffer [] = DeadCodeHelper::composeMethodKey ($ className , $ methodName );
93
102
}
94
-
95
- return $ result !== [] ? $ result : null ;
96
103
}
97
104
98
- /**
99
- * @return list<string>|null
100
- */
101
105
private function registerStaticCall (
102
106
StaticCall $ staticCall ,
103
107
Scope $ scope
104
- ): ? array
108
+ ): void
105
109
{
106
110
$ methodName = $ this ->getMethodName ($ staticCall );
107
111
108
112
if ($ methodName === null ) {
109
- return null ;
113
+ return ;
110
114
}
111
115
112
116
if ($ staticCall ->class instanceof Expr) {
@@ -124,26 +128,19 @@ private function registerStaticCall(
124
128
}
125
129
}
126
130
127
- $ result = [];
128
-
129
131
foreach ($ classReflections as $ classWithMethod ) {
130
132
$ className = $ classWithMethod ->getMethod ($ methodName , $ scope )->getDeclaringClass ()->getName ();
131
- $ result [] = DeadCodeHelper::composeMethodKey ($ className , $ methodName );
133
+ $ this -> callsBuffer [] = DeadCodeHelper::composeMethodKey ($ className , $ methodName );
132
134
}
133
-
134
- return $ result !== [] ? $ result : null ;
135
135
}
136
136
137
- /**
138
- * @return list<string>|null
139
- */
140
137
private function registerFuncCall (
141
138
FuncCall $ functionCall ,
142
139
Scope $ scope
143
- ): ? array
140
+ ): void
144
141
{
145
142
if (!$ functionCall ->name instanceof Name || $ functionCall ->name ->toString () !== 'array_map ' ) { // we should support all native fns
146
- return null ;
143
+ return ;
147
144
}
148
145
149
146
$ callableType = $ scope ->getType ($ functionCall ->getArgs ()[0 ]->value );
@@ -152,24 +149,16 @@ private function registerFuncCall(
152
149
foreach ($ callableType ->getConstantArrays () as $ constantArray ) {
153
150
$ callableTypeAndNames = $ constantArray ->findTypeAndMethodNames ();
154
151
155
- $ result = [];
156
-
157
152
foreach ($ callableTypeAndNames as $ typeAndName ) {
158
153
$ methodName = $ typeAndName ->getMethod ();
159
154
160
155
foreach ($ this ->getReflectionsWithMethod ($ typeAndName ->getType (), $ methodName ) as $ classWithMethod ) {
161
156
$ className = $ classWithMethod ->getMethod ($ methodName , $ scope )->getDeclaringClass ()->getName ();
162
- $ result [] = DeadCodeHelper::composeMethodKey ($ className , $ methodName );
157
+ $ this -> callsBuffer [] = DeadCodeHelper::composeMethodKey ($ className , $ methodName );
163
158
}
164
159
}
165
-
166
- if ($ result !== []) {
167
- return $ result ;
168
- }
169
160
}
170
161
}
171
-
172
- return null ;
173
162
}
174
163
175
164
/**
0 commit comments