33namespace PHPStan \Rules \Variables ;
44
55use PhpParser \Node ;
6+ use PhpParser \Node \Expr \BinaryOp \Identical ;
67use PhpParser \Node \Expr \Variable ;
8+ use PhpParser \Node \Scalar \String_ ;
79use PHPStan \Analyser \Scope ;
10+ use PHPStan \Rules \IdentifierRuleError ;
811use PHPStan \Rules \Rule ;
912use PHPStan \Rules \RuleErrorBuilder ;
13+ use function array_merge ;
1014use function in_array ;
1115use function is_string ;
1216use function sprintf ;
@@ -31,11 +35,31 @@ public function getNodeType(): string
3135
3236 public function processNode (Node $ node , Scope $ scope ): array
3337 {
34- if (!is_string ($ node ->name )) {
35- return [];
38+ $ errors = [];
39+ if (is_string ($ node ->name )) {
40+ $ variableNameScopes = [$ node ->name => $ scope ];
41+ } else {
42+ $ nameType = $ scope ->getType ($ node ->name );
43+ $ variableNameScopes = [];
44+ foreach ($ nameType ->getConstantStrings () as $ constantString ) {
45+ $ name = $ constantString ->getValue ();
46+ $ variableNameScopes [$ name ] = $ scope ->filterByTruthyValue (new Identical ($ node ->name , new String_ ($ name )));
47+ }
48+ }
49+
50+ foreach ($ variableNameScopes as $ name => $ variableScope ) {
51+ $ errors = array_merge ($ errors , $ this ->processSingleVariable ($ variableScope , $ node , $ name ));
3652 }
3753
38- if ($ this ->cliArgumentsVariablesRegistered && in_array ($ node ->name , [
54+ return $ errors ;
55+ }
56+
57+ /**
58+ * @return list<IdentifierRuleError>
59+ */
60+ private function processSingleVariable (Scope $ scope , Variable $ node , string $ variableName ): array
61+ {
62+ if ($ this ->cliArgumentsVariablesRegistered && in_array ($ variableName , [
3963 'argc ' ,
4064 'argv ' ,
4165 ], true )) {
@@ -49,18 +73,18 @@ public function processNode(Node $node, Scope $scope): array
4973 return [];
5074 }
5175
52- if ($ scope ->hasVariableType ($ node -> name )->no ()) {
76+ if ($ scope ->hasVariableType ($ variableName )->no ()) {
5377 return [
54- RuleErrorBuilder::message (sprintf ('Undefined variable: $%s ' , $ node -> name ))
78+ RuleErrorBuilder::message (sprintf ('Undefined variable: $%s ' , $ variableName ))
5579 ->identifier ('variable.undefined ' )
5680 ->build (),
5781 ];
5882 } elseif (
5983 $ this ->checkMaybeUndefinedVariables
60- && !$ scope ->hasVariableType ($ node -> name )->yes ()
84+ && !$ scope ->hasVariableType ($ variableName )->yes ()
6185 ) {
6286 return [
63- RuleErrorBuilder::message (sprintf ('Variable $%s might not be defined. ' , $ node -> name ))
87+ RuleErrorBuilder::message (sprintf ('Variable $%s might not be defined. ' , $ variableName ))
6488 ->identifier ('variable.undefined ' )
6589 ->build (),
6690 ];
0 commit comments