File tree Expand file tree Collapse file tree 4 files changed +117
-5
lines changed
data/not-autoloaded/used-symbols Expand file tree Collapse file tree 4 files changed +117
-5
lines changed Original file line number Diff line number Diff line change @@ -91,7 +91,10 @@ public function parseUsedSymbols(
9191 case T_INTERFACE :
9292 case T_TRAIT :
9393 case T_ENUM :
94- $ inClassLevel = $ level + 1 ;
94+ if (!$ this ->isKeywordUsedAsConstantName ()) {
95+ $ inClassLevel = $ level + 1 ;
96+ }
97+
9598 break ;
9699
97100 case T_USE :
@@ -109,10 +112,12 @@ public function parseUsedSymbols(
109112 break ;
110113
111114 case T_NAMESPACE :
112- // namespace change
113- $ inGlobalScope = false ;
114- $ useStatements = [];
115- $ useStatementKinds = [];
115+ if (!$ this ->isKeywordUsedAsConstantName ()) {
116+ $ inGlobalScope = false ;
117+ $ useStatements = [];
118+ $ useStatementKinds = [];
119+ }
120+
116121 break ;
117122
118123 case T_NAME_FULLY_QUALIFIED :
@@ -361,6 +366,18 @@ private function canBeSymbolName(
361366 return true ;
362367 }
363368
369+ /**
370+ * Checks if the current keyword token is used as a constant name.
371+ * E.g., SomeClass::NAMESPACE (access) or public const INTERFACE = 'value' (definition)
372+ */
373+ private function isKeywordUsedAsConstantName (): bool
374+ {
375+ $ tokenBefore = $ this ->getTokenBefore ($ this ->pointer - 2 );
376+
377+ return $ tokenBefore ->id === T_DOUBLE_COLON
378+ || $ tokenBefore ->id === T_CONST ;
379+ }
380+
364381 private function getTokenBefore (int $ pointer ): PhpToken
365382 {
366383 while ($ pointer >= 0 ) {
Original file line number Diff line number Diff line change @@ -213,6 +213,30 @@ public static function provideVariants(): iterable
213213 ],
214214 ];
215215
216+ // https://github.com/shipmonk-rnd/composer-dependency-analyser/issues/256
217+ yield 'namespace keyword as constant ' => [
218+ __DIR__ . '/data/not-autoloaded/used-symbols/namespace-keyword-constant.php ' ,
219+ [
220+ SymbolKind::CLASSLIKE => [
221+ // Line 15: after "public const NAMESPACE = ..." (T_CONST case)
222+ // Line 27: after "ConstClass::NAMESPACE" (T_DOUBLE_COLON case)
223+ 'Carbon\Carbon ' => [15 , 27 ],
224+ ],
225+ ],
226+ ];
227+
228+ // Related to #256: CLASS/INTERFACE/TRAIT/ENUM keywords can also be constant names
229+ yield 'class keyword as constant ' => [
230+ __DIR__ . '/data/not-autoloaded/used-symbols/class-keyword-constant.php ' ,
231+ [
232+ SymbolKind::CLASSLIKE => [
233+ // Line 16: after "public const TRAIT = ..." (T_CONST case)
234+ // Line 37: after "Other::CLASS" and closure (T_DOUBLE_COLON case)
235+ 'Carbon\Carbon ' => [16 , 37 ],
236+ ],
237+ ],
238+ ];
239+
216240 if (PHP_VERSION_ID >= 80_400 ) {
217241 yield 'property hooks ' => [
218242 __DIR__ . '/data/not-autoloaded/used-symbols/property-hooks.php ' ,
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ namespace App ;
4+
5+ use Carbon \Carbon ;
6+
7+ class ConstHolder
8+ {
9+ // T_TRAIT after T_CONST - should not corrupt $inClassLevel
10+ // (CLASS cannot be used as constant name - it's reserved for ::class)
11+ public const TRAIT = 'some-trait ' ;
12+
13+ public function test (): void
14+ {
15+ // Carbon should be detected here (after const TRAIT definition)
16+ Carbon::now ();
17+ }
18+ }
19+
20+ class Foo
21+ {
22+ public function method (): void
23+ {
24+ // T_CLASS after T_DOUBLE_COLON - should not corrupt $inClassLevel
25+ $ x = Other::CLASS ;
26+
27+ $ fn = function () {
28+ // closure that could cause spurious $inClassLevel reset
29+ };
30+ }
31+
32+ use App \SomeTrait; // trait use, NOT an import - should be ignored
33+
34+ public function bar (): void
35+ {
36+ // Carbon should be detected here (after ::CLASS and closure)
37+ Carbon::now ();
38+ }
39+ }
40+
41+ // SomeTrait should NOT be in use statements (trait use is not import)
42+ new SomeTrait ();
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ namespace App ;
4+
5+ use Carbon \Carbon ;
6+
7+ class ConstClass
8+ {
9+ // T_NAMESPACE after T_CONST - should not reset use statements
10+ public const NAMESPACE = 'some-namespace ' ;
11+
12+ public function test (): void
13+ {
14+ // Carbon should be detected here (after const NAMESPACE definition)
15+ Carbon::now ();
16+ }
17+ }
18+
19+ class IssueHere
20+ {
21+ public function init (): void
22+ {
23+ // T_NAMESPACE after T_DOUBLE_COLON - should not reset use statements
24+ $ namespace = ConstClass::NAMESPACE ;
25+
26+ // Carbon should still be detected here (after ::NAMESPACE access)
27+ Carbon::now ();
28+ }
29+ }
You can’t perform that action at this time.
0 commit comments