6
6
use PhpParser \Node ;
7
7
use PhpParser \Node \Expr ;
8
8
use PHPStan \Analyser \Scope ;
9
- use PHPStan \Node \UnreachableStatementNode ;
9
+ use PHPStan \Node \InClassMethodNode ;
10
+ use PHPStan \Node \InClassNode ;
11
+ use PHPStan \Node \InFunctionNode ;
12
+ use PHPStan \Node \VirtualNode ;
10
13
use PHPStan \Rules \Rule ;
11
14
use PHPStan \Rules \RuleErrorBuilder ;
12
15
use PHPStan \Type \FileTypeMapper ;
@@ -19,9 +22,15 @@ class WrongVariableNameInVarTagRule implements Rule
19
22
20
23
private FileTypeMapper $ fileTypeMapper ;
21
24
22
- public function __construct (FileTypeMapper $ fileTypeMapper )
25
+ private bool $ checkWrongVarUsage ;
26
+
27
+ public function __construct (
28
+ FileTypeMapper $ fileTypeMapper ,
29
+ bool $ checkWrongVarUsage = false
30
+ )
23
31
{
24
32
$ this ->fileTypeMapper = $ fileTypeMapper ;
33
+ $ this ->checkWrongVarUsage = $ checkWrongVarUsage ;
25
34
}
26
35
27
36
public function getNodeType (): string
@@ -36,7 +45,7 @@ public function processNode(Node $node, Scope $scope): array
36
45
|| $ node instanceof Node \Stmt \PropertyProperty
37
46
|| $ node instanceof Node \Stmt \ClassConst
38
47
|| $ node instanceof Node \Stmt \Const_
39
- || $ node instanceof UnreachableStatementNode
48
+ || ( $ node instanceof VirtualNode && ! $ node instanceof InFunctionNode && ! $ node instanceof InClassMethodNode && ! $ node instanceof InClassNode)
40
49
) {
41
50
return [];
42
51
}
@@ -83,6 +92,30 @@ public function processNode(Node $node, Scope $scope): array
83
92
return $ this ->processGlobal ($ scope , $ node , $ varTags );
84
93
}
85
94
95
+ if ($ node instanceof InClassNode || $ node instanceof InClassMethodNode || $ node instanceof InFunctionNode) {
96
+ if ($ this ->checkWrongVarUsage ) {
97
+ $ description = 'a function ' ;
98
+ $ originalNode = $ node ->getOriginalNode ();
99
+ if ($ originalNode instanceof Node \Stmt \Interface_) {
100
+ $ description = 'an interface ' ;
101
+ } elseif ($ originalNode instanceof Node \Stmt \Class_) {
102
+ $ description = 'a class ' ;
103
+ } elseif ($ originalNode instanceof Node \Stmt \Trait_) {
104
+ throw new \PHPStan \ShouldNotHappenException ();
105
+ } elseif ($ originalNode instanceof Node \Stmt \ClassMethod) {
106
+ $ description = 'a method ' ;
107
+ }
108
+ return [
109
+ RuleErrorBuilder::message (sprintf (
110
+ 'PHPDoc tag @var above %s has no effect. ' ,
111
+ $ description
112
+ ))->build (),
113
+ ];
114
+ }
115
+
116
+ return [];
117
+ }
118
+
86
119
return $ this ->processStmt ($ scope , $ varTags , null );
87
120
}
88
121
0 commit comments