@@ -73,6 +73,10 @@ public function processNode(Node $node, Scope $scope): array
7373 return $ this ->processStmt ($ scope , $ varTags , $ node ->expr );
7474 }
7575
76+ if ($ node instanceof Node \Stmt \Global_) {
77+ return $ this ->processGlobal ($ scope , $ node , $ varTags );
78+ }
79+
7680 return $ this ->processStmt ($ scope , $ varTags , null );
7781 }
7882
@@ -285,4 +289,52 @@ private function processStmt(Scope $scope, array $varTags, ?Expr $defaultExpr):
285289 return $ errors ;
286290 }
287291
292+ /**
293+ * @param \PHPStan\Analyser\Scope $scope
294+ * @param \PHPStan\PhpDoc\Tag\VarTag[] $varTags
295+ * @return \PHPStan\Rules\RuleError[]
296+ */
297+ private function processGlobal (Scope $ scope , Node \Stmt \Global_ $ node , array $ varTags ): array
298+ {
299+ $ variableNames = [];
300+ foreach ($ node ->vars as $ var ) {
301+ if (!$ var instanceof Expr \Variable) {
302+ continue ;
303+ }
304+ if (!is_string ($ var ->name )) {
305+ continue ;
306+ }
307+
308+ $ variableNames [$ var ->name ] = true ;
309+ }
310+
311+ $ errors = [];
312+ foreach (array_keys ($ varTags ) as $ name ) {
313+ if (is_int ($ name )) {
314+ if (count ($ variableNames ) === 1 ) {
315+ continue ;
316+ }
317+
318+ $ errors [] = RuleErrorBuilder::message (
319+ 'PHPDoc tag @var above multiple global variables does not specify variable name. '
320+ )->build ();
321+ continue ;
322+ }
323+
324+ if (isset ($ variableNames [$ name ])) {
325+ continue ;
326+ }
327+
328+ $ errors [] = RuleErrorBuilder::message (sprintf (
329+ 'Variable $%s in PHPDoc tag @var does not match any global variable: %s ' ,
330+ $ name ,
331+ implode (', ' , array_map (static function (string $ name ): string {
332+ return sprintf ('$%s ' , $ name );
333+ }, array_keys ($ variableNames )))
334+ ))->build ();
335+ }
336+
337+ return $ errors ;
338+ }
339+
288340}
0 commit comments