@@ -177,6 +177,8 @@ final class MutatingScope implements Scope
177
177
178
178
private const KEEP_VOID_ATTRIBUTE_NAME = 'keepVoid ' ;
179
179
180
+ private const IS_GLOBAL_ATTRIBUTE_NAME = 'isGlobal ' ;
181
+
180
182
/** @var Type[] */
181
183
private array $ resolvedTypes = [];
182
184
@@ -584,10 +586,25 @@ public function afterOpenSslCall(string $openSslFunctionName): self
584
586
);
585
587
}
586
588
589
+ /** @api */
590
+ public function isGlobalVariable (string $ variableName ): bool
591
+ {
592
+ if ($ this ->isSuperglobalVariable ($ variableName )) {
593
+ return true ;
594
+ }
595
+
596
+ $ varExprString = '$ ' . $ variableName ;
597
+ if (!isset ($ this ->expressionTypes [$ varExprString ])) {
598
+ return false ;
599
+ }
600
+
601
+ return $ this ->expressionTypes [$ varExprString ]->getExpr ()->getAttribute (self ::IS_GLOBAL_ATTRIBUTE_NAME ) === true ;
602
+ }
603
+
587
604
/** @api */
588
605
public function hasVariableType (string $ variableName ): TrinaryLogic
589
606
{
590
- if ($ this ->isGlobalVariable ($ variableName )) {
607
+ if ($ this ->isSuperglobalVariable ($ variableName )) {
591
608
return TrinaryLogic::createYes ();
592
609
}
593
610
@@ -628,7 +645,7 @@ public function getVariableType(string $variableName): Type
628
645
629
646
$ varExprString = '$ ' . $ variableName ;
630
647
if (!array_key_exists ($ varExprString , $ this ->expressionTypes )) {
631
- if ($ this ->isGlobalVariable ($ variableName )) {
648
+ if ($ this ->isSuperglobalVariable ($ variableName )) {
632
649
return new ArrayType (new BenevolentUnionType ([new IntegerType (), new StringType ()]), new MixedType (true ));
633
650
}
634
651
return new MixedType ();
@@ -679,7 +696,7 @@ public function getMaybeDefinedVariables(): array
679
696
return $ variables ;
680
697
}
681
698
682
- private function isGlobalVariable (string $ variableName ): bool
699
+ private function isSuperglobalVariable (string $ variableName ): bool
683
700
{
684
701
return in_array ($ variableName , self ::SUPERGLOBAL_VARIABLES , true );
685
702
}
@@ -4168,9 +4185,13 @@ public function isUndefinedExpressionAllowed(Expr $expr): bool
4168
4185
return array_key_exists ($ exprString , $ this ->currentlyAllowedUndefinedExpressions );
4169
4186
}
4170
4187
4171
- public function assignVariable (string $ variableName , Type $ type , Type $ nativeType , TrinaryLogic $ certainty ): self
4188
+ public function assignVariable (string $ variableName , Type $ type , Type $ nativeType , TrinaryLogic $ certainty, bool $ isGlobal = false ): self
4172
4189
{
4173
4190
$ node = new Variable ($ variableName );
4191
+ if ($ isGlobal || $ this ->isGlobalVariable ($ variableName )) {
4192
+ $ node ->setAttribute (self ::IS_GLOBAL_ATTRIBUTE_NAME , true );
4193
+ }
4194
+
4174
4195
$ scope = $ this ->assignExpression ($ node , $ type , $ nativeType );
4175
4196
if ($ certainty ->no ()) {
4176
4197
throw new ShouldNotHappenException ();
@@ -4945,7 +4966,7 @@ private function createConditionalExpressions(
4945
4966
private function mergeVariableHolders (array $ ourVariableTypeHolders , array $ theirVariableTypeHolders ): array
4946
4967
{
4947
4968
$ intersectedVariableTypeHolders = [];
4948
- $ globalVariableCallback = fn (Node $ node ) => $ node instanceof Variable && is_string ($ node ->name ) && $ this ->isGlobalVariable ($ node ->name );
4969
+ $ globalVariableCallback = fn (Node $ node ) => $ node instanceof Variable && is_string ($ node ->name ) && $ this ->isSuperglobalVariable ($ node ->name );
4949
4970
$ nodeFinder = new NodeFinder ();
4950
4971
foreach ($ ourVariableTypeHolders as $ exprString => $ variableTypeHolder ) {
4951
4972
if (isset ($ theirVariableTypeHolders [$ exprString ])) {
0 commit comments