@@ -202,6 +202,7 @@ final class MutatingScope implements Scope
202
202
* @param array<string, true> $currentlyAllowedUndefinedExpressions
203
203
* @param array<string, ExpressionTypeHolder> $nativeExpressionTypes
204
204
* @param list<array{MethodReflection|FunctionReflection|null, ParameterReflection|null}> $inFunctionCallsStack
205
+ * @param list<string> $globalVariables
205
206
*/
206
207
public function __construct (
207
208
private InternalScopeFactory $ scopeFactory ,
@@ -235,6 +236,7 @@ public function __construct(
235
236
private bool $ afterExtractCall = false ,
236
237
private ?Scope $ parentScope = null ,
237
238
private bool $ nativeTypesPromoted = false ,
239
+ private array $ globalVariables = [],
238
240
)
239
241
{
240
242
if ($ namespace === '' ) {
@@ -363,6 +365,7 @@ public function rememberConstructorScope(): self
363
365
$ this ->afterExtractCall ,
364
366
$ this ->parentScope ,
365
367
$ this ->nativeTypesPromoted ,
368
+ $ this ->globalVariables ,
366
369
);
367
370
}
368
371
@@ -441,6 +444,7 @@ public function afterExtractCall(): self
441
444
true ,
442
445
$ this ->parentScope ,
443
446
$ this ->nativeTypesPromoted ,
447
+ $ this ->globalVariables ,
444
448
);
445
449
}
446
450
@@ -497,6 +501,7 @@ public function afterClearstatcacheCall(): self
497
501
$ this ->afterExtractCall ,
498
502
$ this ->parentScope ,
499
503
$ this ->nativeTypesPromoted ,
504
+ $ this ->globalVariables ,
500
505
);
501
506
}
502
507
@@ -579,13 +584,14 @@ public function afterOpenSslCall(string $openSslFunctionName): self
579
584
$ this ->afterExtractCall ,
580
585
$ this ->parentScope ,
581
586
$ this ->nativeTypesPromoted ,
587
+ $ this ->globalVariables ,
582
588
);
583
589
}
584
590
585
591
/** @api */
586
592
public function hasVariableType (string $ variableName ): TrinaryLogic
587
593
{
588
- if ($ this ->isGlobalVariable ($ variableName )) {
594
+ if ($ this ->isSuperGlobalVariable ($ variableName )) {
589
595
return TrinaryLogic::createYes ();
590
596
}
591
597
@@ -626,7 +632,7 @@ public function getVariableType(string $variableName): Type
626
632
627
633
$ varExprString = '$ ' . $ variableName ;
628
634
if (!array_key_exists ($ varExprString , $ this ->expressionTypes )) {
629
- if ($ this ->isGlobalVariable ($ variableName )) {
635
+ if ($ this ->isSuperGlobalVariable ($ variableName )) {
630
636
return new ArrayType (new BenevolentUnionType ([new IntegerType (), new StringType ()]), new MixedType (true ));
631
637
}
632
638
return new MixedType ();
@@ -635,6 +641,18 @@ public function getVariableType(string $variableName): Type
635
641
return TypeUtils::resolveLateResolvableTypes ($ this ->expressionTypes [$ varExprString ]->getType ());
636
642
}
637
643
644
+ public function setVariableAsGlobal (string $ variableName ): self
645
+ {
646
+ $ this ->globalVariables [] = $ variableName ;
647
+
648
+ return $ this ;
649
+ }
650
+
651
+ public function isGlobalVariable (string $ variableName ): bool
652
+ {
653
+ return in_array ($ variableName , $ this ->globalVariables , true );
654
+ }
655
+
638
656
/**
639
657
* @api
640
658
* @return list<string>
@@ -677,7 +695,7 @@ public function getMaybeDefinedVariables(): array
677
695
return $ variables ;
678
696
}
679
697
680
- private function isGlobalVariable (string $ variableName ): bool
698
+ private function isSuperGlobalVariable (string $ variableName ): bool
681
699
{
682
700
return in_array ($ variableName , self ::SUPERGLOBAL_VARIABLES , true );
683
701
}
@@ -2762,6 +2780,7 @@ private function promoteNativeTypes(): self
2762
2780
$ this ->afterExtractCall ,
2763
2781
$ this ->parentScope ,
2764
2782
true ,
2783
+ $ this ->globalVariables ,
2765
2784
);
2766
2785
}
2767
2786
@@ -2956,6 +2975,7 @@ public function pushInFunctionCall($reflection, ?ParameterReflection $parameter)
2956
2975
$ this ->afterExtractCall ,
2957
2976
$ this ->parentScope ,
2958
2977
$ this ->nativeTypesPromoted ,
2978
+ $ this ->globalVariables ,
2959
2979
);
2960
2980
}
2961
2981
@@ -2981,6 +3001,7 @@ public function popInFunctionCall(): self
2981
3001
$ this ->afterExtractCall ,
2982
3002
$ this ->parentScope ,
2983
3003
$ this ->nativeTypesPromoted ,
3004
+ $ this ->globalVariables ,
2984
3005
);
2985
3006
}
2986
3007
@@ -3572,6 +3593,7 @@ public function restoreThis(self $restoreThisScope): self
3572
3593
$ this ->afterExtractCall ,
3573
3594
$ this ->parentScope ,
3574
3595
$ this ->nativeTypesPromoted ,
3596
+ $ this ->globalVariables ,
3575
3597
);
3576
3598
}
3577
3599
@@ -3635,6 +3657,7 @@ public function enterAnonymousFunction(
3635
3657
false ,
3636
3658
$ this ,
3637
3659
$ this ->nativeTypesPromoted ,
3660
+ [],
3638
3661
);
3639
3662
}
3640
3663
@@ -3743,6 +3766,7 @@ private function enterAnonymousFunctionWithoutReflection(
3743
3766
false ,
3744
3767
$ this ,
3745
3768
$ this ->nativeTypesPromoted ,
3769
+ [],
3746
3770
);
3747
3771
}
3748
3772
@@ -3811,6 +3835,7 @@ public function enterArrowFunction(Expr\ArrowFunction $arrowFunction, ?array $ca
3811
3835
$ scope ->afterExtractCall ,
3812
3836
$ scope ->parentScope ,
3813
3837
$ this ->nativeTypesPromoted ,
3838
+ [],
3814
3839
);
3815
3840
}
3816
3841
@@ -3870,6 +3895,7 @@ private function enterArrowFunctionWithoutReflection(Expr\ArrowFunction $arrowFu
3870
3895
$ arrowFunctionScope ->afterExtractCall ,
3871
3896
$ arrowFunctionScope ->parentScope ,
3872
3897
$ this ->nativeTypesPromoted ,
3898
+ [],
3873
3899
);
3874
3900
}
3875
3901
@@ -4033,6 +4059,7 @@ public function enterExpressionAssign(Expr $expr): self
4033
4059
$ this ->afterExtractCall ,
4034
4060
$ this ->parentScope ,
4035
4061
$ this ->nativeTypesPromoted ,
4062
+ $ this ->globalVariables ,
4036
4063
);
4037
4064
$ scope ->resolvedTypes = $ this ->resolvedTypes ;
4038
4065
$ scope ->truthyScopes = $ this ->truthyScopes ;
@@ -4064,6 +4091,7 @@ public function exitExpressionAssign(Expr $expr): self
4064
4091
$ this ->afterExtractCall ,
4065
4092
$ this ->parentScope ,
4066
4093
$ this ->nativeTypesPromoted ,
4094
+ $ this ->globalVariables ,
4067
4095
);
4068
4096
$ scope ->resolvedTypes = $ this ->resolvedTypes ;
4069
4097
$ scope ->truthyScopes = $ this ->truthyScopes ;
@@ -4106,6 +4134,7 @@ public function setAllowedUndefinedExpression(Expr $expr): self
4106
4134
$ this ->afterExtractCall ,
4107
4135
$ this ->parentScope ,
4108
4136
$ this ->nativeTypesPromoted ,
4137
+ $ this ->globalVariables ,
4109
4138
);
4110
4139
$ scope ->resolvedTypes = $ this ->resolvedTypes ;
4111
4140
$ scope ->truthyScopes = $ this ->truthyScopes ;
@@ -4137,6 +4166,7 @@ public function unsetAllowedUndefinedExpression(Expr $expr): self
4137
4166
$ this ->afterExtractCall ,
4138
4167
$ this ->parentScope ,
4139
4168
$ this ->nativeTypesPromoted ,
4169
+ $ this ->globalVariables ,
4140
4170
);
4141
4171
$ scope ->resolvedTypes = $ this ->resolvedTypes ;
4142
4172
$ scope ->truthyScopes = $ this ->truthyScopes ;
@@ -4284,6 +4314,7 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType,
4284
4314
$ this ->afterExtractCall ,
4285
4315
$ this ->parentScope ,
4286
4316
$ this ->nativeTypesPromoted ,
4317
+ $ this ->globalVariables ,
4287
4318
);
4288
4319
4289
4320
if ($ expr instanceof AlwaysRememberedExpr) {
@@ -4393,6 +4424,7 @@ public function invalidateExpression(Expr $expressionToInvalidate, bool $require
4393
4424
$ this ->afterExtractCall ,
4394
4425
$ this ->parentScope ,
4395
4426
$ this ->nativeTypesPromoted ,
4427
+ $ this ->globalVariables ,
4396
4428
);
4397
4429
}
4398
4430
@@ -4493,6 +4525,7 @@ private function invalidateMethodsOnExpression(Expr $expressionToInvalidate): se
4493
4525
$ this ->afterExtractCall ,
4494
4526
$ this ->parentScope ,
4495
4527
$ this ->nativeTypesPromoted ,
4528
+ $ this ->globalVariables ,
4496
4529
);
4497
4530
}
4498
4531
@@ -4705,6 +4738,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
4705
4738
$ scope ->afterExtractCall ,
4706
4739
$ scope ->parentScope ,
4707
4740
$ scope ->nativeTypesPromoted ,
4741
+ $ this ->globalVariables ,
4708
4742
);
4709
4743
}
4710
4744
@@ -4732,6 +4766,7 @@ public function addConditionalExpressions(string $exprString, array $conditional
4732
4766
$ this ->afterExtractCall ,
4733
4767
$ this ->parentScope ,
4734
4768
$ this ->nativeTypesPromoted ,
4769
+ $ this ->globalVariables ,
4735
4770
);
4736
4771
}
4737
4772
@@ -4762,6 +4797,7 @@ public function exitFirstLevelStatements(): self
4762
4797
$ this ->afterExtractCall ,
4763
4798
$ this ->parentScope ,
4764
4799
$ this ->nativeTypesPromoted ,
4800
+ $ this ->globalVariables ,
4765
4801
);
4766
4802
$ scope ->resolvedTypes = $ this ->resolvedTypes ;
4767
4803
$ scope ->truthyScopes = $ this ->truthyScopes ;
@@ -4799,6 +4835,9 @@ public function mergeWith(?self $otherScope): self
4799
4835
$ ourExpressionTypes ,
4800
4836
$ mergedExpressionTypes ,
4801
4837
);
4838
+
4839
+ $ mergedGlobalVariables = array_merge ($ this ->globalVariables , $ otherScope ->globalVariables );
4840
+
4802
4841
return $ this ->scopeFactory ->create (
4803
4842
$ this ->context ,
4804
4843
$ this ->isDeclareStrictTypes (),
@@ -4816,6 +4855,7 @@ public function mergeWith(?self $otherScope): self
4816
4855
$ this ->afterExtractCall && $ otherScope ->afterExtractCall ,
4817
4856
$ this ->parentScope ,
4818
4857
$ this ->nativeTypesPromoted ,
4858
+ $ mergedGlobalVariables ,
4819
4859
);
4820
4860
}
4821
4861
@@ -4929,7 +4969,7 @@ private function createConditionalExpressions(
4929
4969
private function mergeVariableHolders (array $ ourVariableTypeHolders , array $ theirVariableTypeHolders ): array
4930
4970
{
4931
4971
$ intersectedVariableTypeHolders = [];
4932
- $ globalVariableCallback = fn (Node $ node ) => $ node instanceof Variable && is_string ($ node ->name ) && $ this ->isGlobalVariable ($ node ->name );
4972
+ $ globalVariableCallback = fn (Node $ node ) => $ node instanceof Variable && is_string ($ node ->name ) && $ this ->isSuperGlobalVariable ($ node ->name );
4933
4973
$ nodeFinder = new NodeFinder ();
4934
4974
foreach ($ ourVariableTypeHolders as $ exprString => $ variableTypeHolder ) {
4935
4975
if (isset ($ theirVariableTypeHolders [$ exprString ])) {
@@ -5020,6 +5060,7 @@ public function processFinallyScope(self $finallyScope, self $originalFinallySco
5020
5060
$ this ->afterExtractCall ,
5021
5061
$ this ->parentScope ,
5022
5062
$ this ->nativeTypesPromoted ,
5063
+ $ this ->globalVariables ,
5023
5064
);
5024
5065
}
5025
5066
@@ -5115,6 +5156,7 @@ public function processClosureScope(
5115
5156
$ this ->afterExtractCall ,
5116
5157
$ this ->parentScope ,
5117
5158
$ this ->nativeTypesPromoted ,
5159
+ $ this ->globalVariables ,
5118
5160
);
5119
5161
}
5120
5162
@@ -5164,6 +5206,7 @@ public function processAlwaysIterableForeachScopeWithoutPollute(self $finalScope
5164
5206
$ this ->afterExtractCall ,
5165
5207
$ this ->parentScope ,
5166
5208
$ this ->nativeTypesPromoted ,
5209
+ $ this ->globalVariables ,
5167
5210
);
5168
5211
}
5169
5212
@@ -5195,6 +5238,7 @@ public function generalizeWith(self $otherScope): self
5195
5238
$ this ->afterExtractCall ,
5196
5239
$ this ->parentScope ,
5197
5240
$ this ->nativeTypesPromoted ,
5241
+ $ this ->globalVariables ,
5198
5242
);
5199
5243
}
5200
5244
0 commit comments