31
31
use const T_USE ;
32
32
use const T_WHITESPACE ;
33
33
34
+ // phpcs:disable Squiz.PHP.CommentedOutCode.Found
35
+
34
36
class UsedSymbolExtractor
35
37
{
36
38
@@ -68,8 +70,10 @@ public function parseUsedSymbols(): array
68
70
$ useStatements = [];
69
71
$ useStatementKinds = [];
70
72
71
- $ level = 0 ;
73
+ $ level = 0 ; // {, }, {$, ${
74
+ $ squareLevel = 0 ; // [, ], #[
72
75
$ inClassLevel = null ;
76
+ $ inAttributeSquareLevel = null ;
73
77
74
78
$ numTokens = $ this ->numTokens ;
75
79
$ tokens = $ this ->tokens ;
@@ -96,13 +100,17 @@ public function parseUsedSymbols(): array
96
100
97
101
break ;
98
102
103
+ case PHP_VERSION_ID > 80000 ? T_ATTRIBUTE : -1 :
104
+ $ inAttributeSquareLevel = ++$ squareLevel ;
105
+ break ;
106
+
99
107
case PHP_VERSION_ID >= 80000 ? T_NAMESPACE : -1 :
100
108
$ useStatements = []; // reset use statements on namespace change
101
109
break ;
102
110
103
111
case PHP_VERSION_ID >= 80000 ? T_NAME_FULLY_QUALIFIED : -1 :
104
112
$ symbolName = $ this ->normalizeBackslash ($ token [1 ]);
105
- $ kind = $ this ->getFqnSymbolKind ($ this ->pointer - 2 , $ this ->pointer );
113
+ $ kind = $ this ->getFqnSymbolKind ($ this ->pointer - 2 , $ this ->pointer , $ inAttributeSquareLevel !== null );
106
114
$ usedSymbols [$ kind ][$ symbolName ][] = $ token [2 ];
107
115
break ;
108
116
@@ -111,7 +119,7 @@ public function parseUsedSymbols(): array
111
119
112
120
if (isset ($ useStatements [$ neededAlias ])) {
113
121
$ symbolName = $ useStatements [$ neededAlias ] . substr ($ token [1 ], strlen ($ neededAlias ));
114
- $ kind = $ this ->getFqnSymbolKind ($ this ->pointer - 2 , $ this ->pointer );
122
+ $ kind = $ this ->getFqnSymbolKind ($ this ->pointer - 2 , $ this ->pointer , $ inAttributeSquareLevel !== null );
115
123
$ usedSymbols [$ kind ][$ symbolName ][] = $ token [2 ];
116
124
}
117
125
@@ -143,7 +151,7 @@ public function parseUsedSymbols(): array
143
151
$ symbolName = $ this ->normalizeBackslash ($ this ->parseNameForOldPhp ());
144
152
145
153
if ($ symbolName !== '' ) { // e.g. \array (NS separator followed by not-a-name)
146
- $ kind = $ this ->getFqnSymbolKind ($ pointerBeforeName , $ this ->pointer - 1 );
154
+ $ kind = $ this ->getFqnSymbolKind ($ pointerBeforeName , $ this ->pointer - 1 , false );
147
155
$ usedSymbols [$ kind ][$ symbolName ][] = $ token [2 ];
148
156
}
149
157
@@ -163,7 +171,7 @@ public function parseUsedSymbols(): array
163
171
164
172
if (isset ($ useStatements [$ neededAlias ])) { // qualified name
165
173
$ symbolName = $ useStatements [$ neededAlias ] . substr ($ name , strlen ($ neededAlias ));
166
- $ kind = $ this ->getFqnSymbolKind ($ pointerBeforeName , $ this ->pointer - 1 );
174
+ $ kind = $ this ->getFqnSymbolKind ($ pointerBeforeName , $ this ->pointer - 1 , false );
167
175
$ usedSymbols [$ kind ][$ symbolName ][] = $ token [2 ];
168
176
}
169
177
}
@@ -183,6 +191,14 @@ public function parseUsedSymbols(): array
183
191
}
184
192
185
193
$ level --;
194
+ } elseif ($ token === '[ ' ) {
195
+ $ squareLevel ++;
196
+ } elseif ($ token === '] ' ) {
197
+ if ($ squareLevel === $ inAttributeSquareLevel ) {
198
+ $ inAttributeSquareLevel = null ;
199
+ }
200
+
201
+ $ squareLevel --;
186
202
}
187
203
}
188
204
@@ -306,8 +322,16 @@ private function normalizeBackslash(string $class): string
306
322
/**
307
323
* @return SymbolKind::CLASSLIKE|SymbolKind::FUNCTION
308
324
*/
309
- private function getFqnSymbolKind (int $ pointerBeforeName , int $ pointerAfterName ): int
325
+ private function getFqnSymbolKind (
326
+ int $ pointerBeforeName ,
327
+ int $ pointerAfterName ,
328
+ bool $ inAttribute
329
+ ): int
310
330
{
331
+ if ($ inAttribute ) {
332
+ return SymbolKind::CLASSLIKE ;
333
+ }
334
+
311
335
do {
312
336
$ tokenBeforeName = $ this ->tokens [$ pointerBeforeName ];
313
337
@@ -338,13 +362,9 @@ private function getFqnSymbolKind(int $pointerBeforeName, int $pointerAfterName)
338
362
break ;
339
363
} while ($ pointerAfterName < $ this ->numTokens );
340
364
341
- // phpcs:disable Squiz.PHP.CommentedOutCode.Found
342
365
if (
343
366
$ tokenAfterName === '( '
344
- && !(
345
- $ tokenBeforeName [0 ] === T_NEW // eliminate new \ClassName(
346
- || (PHP_VERSION_ID > 80000 && $ tokenBeforeName [0 ] === T_ATTRIBUTE ) // eliminate #[\AttributeName(
347
- )
367
+ && $ tokenBeforeName [0 ] !== T_NEW // eliminate new \ClassName(
348
368
) {
349
369
return SymbolKind::FUNCTION ;
350
370
}
0 commit comments