2
2
3
3
namespace PHPStan \Reflection \Php ;
4
4
5
- use PhpParser \Node ;
6
- use PhpParser \Node \Stmt \Function_ ;
7
5
use PHPStan \BetterReflection \Reflection \Adapter \ReflectionFunction ;
8
6
use PHPStan \BetterReflection \Reflection \Adapter \ReflectionParameter ;
9
- use PHPStan \Cache \Cache ;
10
- use PHPStan \Parser \FunctionCallStatementFinder ;
11
7
use PHPStan \Parser \Parser ;
8
+ use PHPStan \Parser \VariadicFunctionsVisitor ;
12
9
use PHPStan \Reflection \Assertions ;
13
10
use PHPStan \Reflection \ExtendedFunctionVariant ;
14
11
use PHPStan \Reflection \ExtendedParameterReflection ;
15
12
use PHPStan \Reflection \ExtendedParametersAcceptor ;
16
13
use PHPStan \Reflection \FunctionReflection ;
17
14
use PHPStan \Reflection \InitializerExprTypeResolver ;
18
- use PHPStan \Reflection \ParametersAcceptor ;
19
15
use PHPStan \TrinaryLogic ;
20
16
use PHPStan \Type \Generic \TemplateTypeMap ;
21
17
use PHPStan \Type \MixedType ;
22
18
use PHPStan \Type \Type ;
23
19
use PHPStan \Type \TypehintHelper ;
24
20
use function array_key_exists ;
25
21
use function array_map ;
26
- use function filemtime ;
22
+ use function count ;
27
23
use function is_array ;
28
24
use function is_file ;
29
- use function sprintf ;
30
- use function time ;
31
25
32
26
final class PhpFunctionReflection implements FunctionReflection
33
27
{
34
28
35
29
/** @var list<ExtendedFunctionVariant>|null */
36
30
private ?array $ variants = null ;
37
31
32
+ private ?bool $ containsVariadicCalls = null ;
33
+
38
34
/**
39
35
* @param array<string, Type> $phpDocParameterTypes
40
36
* @param array<string, Type> $phpDocParameterOutTypes
@@ -45,8 +41,6 @@ public function __construct(
45
41
private InitializerExprTypeResolver $ initializerExprTypeResolver ,
46
42
private ReflectionFunction $ reflection ,
47
43
private Parser $ parser ,
48
- private FunctionCallStatementFinder $ functionCallStatementFinder ,
49
- private Cache $ cache ,
50
44
private TemplateTypeMap $ templateTypeMap ,
51
45
private array $ phpDocParameterTypes ,
52
46
private ?Type $ phpDocReturnType ,
@@ -139,67 +133,29 @@ private function getParameters(): array
139
133
private function isVariadic (): bool
140
134
{
141
135
$ isNativelyVariadic = $ this ->reflection ->isVariadic ();
142
- if (!$ isNativelyVariadic && $ this ->reflection
143
- ->getFileName () !== false ) {
144
- $ fileName = $ this ->reflection ->getFileName ();
145
- if (is_file ($ fileName )) {
146
- $ functionName = $ this ->reflection ->getName ();
147
- $ modifiedTime = filemtime ($ fileName );
148
- if ($ modifiedTime === false ) {
149
- $ modifiedTime = time ();
150
- }
151
- $ variableCacheKey = sprintf ('%d-v4 ' , $ modifiedTime );
152
- $ key = sprintf ('variadic-function-%s-%s ' , $ functionName , $ fileName );
153
- $ cachedResult = $ this ->cache ->load ($ key , $ variableCacheKey );
154
- if ($ cachedResult === null ) {
155
- $ nodes = $ this ->parser ->parseFile ($ fileName );
156
- $ result = !$ this ->containsVariadicFunction ($ nodes )->no ();
157
- $ this ->cache ->save ($ key , $ variableCacheKey , $ result );
158
- return $ result ;
159
- }
136
+ if (!$ isNativelyVariadic && $ this ->reflection ->getFileName () !== false ) {
137
+ $ filename = $ this ->reflection ->getFileName ();
160
138
161
- return $ cachedResult ;
139
+ if ($ this ->containsVariadicCalls !== null ) {
140
+ return $ this ->containsVariadicCalls ;
162
141
}
163
- }
164
-
165
- return $ isNativelyVariadic ;
166
- }
167
142
168
- /**
169
- * @param Node[]|scalar[]|Node $node
170
- */
171
- private function containsVariadicFunction (array |Node $ node ): TrinaryLogic
172
- {
173
- $ result = TrinaryLogic::createMaybe ();
174
-
175
- if ($ node instanceof Node) {
176
- if ($ node instanceof Function_) {
177
- $ functionName = (string ) $ node ->namespacedName ;
178
-
179
- if ($ functionName === $ this ->reflection ->getName ()) {
180
- return TrinaryLogic::createFromBoolean ($ this ->isFunctionNodeVariadic ($ node ));
181
- }
182
- }
143
+ $ nodes = $ this ->parser ->parseFile ($ filename );
144
+ if (count ($ nodes ) > 0 ) {
145
+ $ variadicFunctions = $ nodes [0 ]->getAttribute (VariadicFunctionsVisitor::ATTRIBUTE_NAME );
183
146
184
- foreach ($ node ->getSubNodeNames () as $ subNodeName ) {
185
- $ innerNode = $ node ->{$ subNodeName };
186
- if (!$ innerNode instanceof Node && !is_array ($ innerNode )) {
187
- continue ;
147
+ if (
148
+ is_array ($ variadicFunctions )
149
+ && array_key_exists ($ this ->reflection ->getName (), $ variadicFunctions )
150
+ ) {
151
+ return $ this ->containsVariadicCalls = !$ variadicFunctions [$ this ->reflection ->getName ()]->no ();
188
152
}
189
-
190
- $ result = $ result ->and ($ this ->containsVariadicFunction ($ innerNode ));
191
153
}
192
- } elseif (is_array ($ node )) {
193
- foreach ($ node as $ subNode ) {
194
- if (!$ subNode instanceof Node) {
195
- continue ;
196
- }
197
154
198
- $ result = $ result ->and ($ this ->containsVariadicFunction ($ subNode ));
199
- }
155
+ return $ this ->containsVariadicCalls = false ;
200
156
}
201
157
202
- return $ result ;
158
+ return $ isNativelyVariadic ;
203
159
}
204
160
205
161
private function getReturnType (): Type
@@ -296,19 +252,4 @@ public function acceptsNamedArguments(): TrinaryLogic
296
252
return TrinaryLogic::createFromBoolean ($ this ->acceptsNamedArguments );
297
253
}
298
254
299
- private function isFunctionNodeVariadic (Function_ $ node ): bool
300
- {
301
- foreach ($ node ->params as $ parameter ) {
302
- if ($ parameter ->variadic ) {
303
- return true ;
304
- }
305
- }
306
-
307
- if ($ this ->functionCallStatementFinder ->findFunctionCallInStatements (ParametersAcceptor::VARIADIC_FUNCTIONS , $ node ->getStmts ()) !== null ) {
308
- return true ;
309
- }
310
-
311
- return false ;
312
- }
313
-
314
255
}
0 commit comments