diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/csl/SemanticAnalysis.java b/php/php.editor/src/org/netbeans/modules/php/editor/csl/SemanticAnalysis.java index 24a357c62325..e09a5a5e71fa 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/csl/SemanticAnalysis.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/csl/SemanticAnalysis.java @@ -367,7 +367,6 @@ public void visit(ClassDeclaration cldec) { } addToPath(cldec); typeInfo = new TypeDeclarationTypeInfo(cldec); - scan(cldec.getAttributes()); scan(cldec.getSuperClass()); scan(cldec.getInterfaces()); Identifier name = cldec.getName(); @@ -375,6 +374,8 @@ public void visit(ClassDeclaration cldec) { needToScan.put(typeInfo, new ArrayList<>()); if (cldec.getBody() != null) { cldec.getBody().accept(this); + // GH-8244 scan attributes after constant declarations are scanned + scan(cldec.getAttributes()); // find all usages in the method bodies scanMethodBodies(); @@ -513,13 +514,14 @@ public void visit(ClassInstanceCreation node) { // GH-5551 keep original type info to scan parent blocks TypeInfo originalTypeInfo = typeInfo; typeInfo = new ClassInstanceCreationTypeInfo(node); - scan(node.getAttributes()); scan(node.getSuperClass()); scan(node.getInterfaces()); needToScan.put(typeInfo, new ArrayList<>()); Block body = node.getBody(); if (body != null) { body.accept(this); + // GH-8244 scan attributes after constant declarations are scanned + scan(node.getAttributes()); // find all usages in the method bodies scanMethodBodies(); @@ -571,7 +573,6 @@ public void visit(EnumDeclaration node) { return; } addToPath(node); - scan(node.getAttributes()); scan(node.getInterfaces()); typeInfo = new TypeDeclarationTypeInfo(node); Identifier name = node.getName(); @@ -579,6 +580,8 @@ public void visit(EnumDeclaration node) { needToScan.put(typeInfo, new ArrayList<>()); if (node.getBody() != null) { node.getBody().accept(this); + // GH-8244 scan attributes after constant declarations are scanned + scan(node.getAttributes()); scanMethodBodies(); addColoringForUnusedPrivateConstants(); } diff --git a/php/php.editor/test/unit/data/testfiles/semantic/gh8244_01.php b/php/php.editor/test/unit/data/testfiles/semantic/gh8244_01.php new file mode 100644 index 000000000000..11b8e74c8f15 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/semantic/gh8244_01.php @@ -0,0 +1,50 @@ +FIELD,STATIC:TARGET_CLASS<|)] +class |>CLASS:SomeAttribute<| +{ + public function |>METHOD:__construct<|(string $name) {} +} + +#[SomeAttribute(|>CUSTOM2:name: <|self::|>FIELD,STATIC:TEST_CLASS<|)] +class |>CLASS:TestClass<| +{ + private const string |>FIELD,STATIC:TEST_CLASS<| = 'test'; +} + +#[SomeAttribute(|>CUSTOM2:name: <|self::|>FIELD,STATIC:TEST_ENUM<|)] +enum |>CLASS:TestEnum<| +{ + private const string |>FIELD,STATIC:TEST_ENUM<| = 'test'; +} + +#[SomeAttribute(|>CUSTOM2:name: <|self::|>FIELD,STATIC:TEST_TRAIT<|)] +trait |>CLASS:TestTrait<| +{ + private const string |>FIELD,STATIC:TEST_TRAIT<| = 'test'; +} + +$anon = new #[SomeAttribute(|>CUSTOM2:name: <|self::|>FIELD,STATIC:TEST_ANON<|)] class() { + private const string |>FIELD,STATIC:TEST_ANON<| = 'test'; +}; diff --git a/php/php.editor/test/unit/data/testfiles/semantic/gh8244_02.php b/php/php.editor/test/unit/data/testfiles/semantic/gh8244_02.php new file mode 100644 index 000000000000..fe825c7be59f --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/semantic/gh8244_02.php @@ -0,0 +1,50 @@ +FIELD,STATIC:TARGET_CLASS<|)] +class |>CLASS:SomeAttribute<| +{ + public function |>METHOD:__construct<|(string $name) {} +} + +#[SomeAttribute(|>CUSTOM2:name: <|TestClass::|>FIELD,STATIC:TEST_CLASS<|)] +class |>CLASS:TestClass<| +{ + private const string |>FIELD,STATIC:TEST_CLASS<| = 'test'; +} + +#[SomeAttribute(|>CUSTOM2:name: <|TestEnum::|>FIELD,STATIC:TEST_ENUM<|)] +enum |>CLASS:TestEnum<| +{ + private const string |>FIELD,STATIC:TEST_ENUM<| = 'test'; +} + +#[SomeAttribute(|>CUSTOM2:name: <|TestTrait::|>FIELD,STATIC:TEST_TRAIT<|)] +trait |>CLASS:TestTrait<| +{ + private const string |>FIELD,STATIC:TEST_TRAIT<| = 'test'; +} + +$anon = new #[SomeAttribute(|>CUSTOM2:name: <|self::|>FIELD,STATIC:TEST_ANON<|)] class() { + private const string |>FIELD,STATIC:TEST_ANON<| = 'test'; +}; diff --git a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/csl/SemanticAnalyzerTest.java b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/csl/SemanticAnalyzerTest.java index 9811eccf7d0d..b656f101dd00 100644 --- a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/csl/SemanticAnalyzerTest.java +++ b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/csl/SemanticAnalyzerTest.java @@ -233,4 +233,12 @@ public void testGH5551_02() throws Exception { public void testDynamicClassConstantFetch_01() throws Exception { checkSemantic("testfiles/semantic/dynamicClassConstantFetch_01.php"); } + + public void testGH8244_01() throws Exception { + checkSemantic("testfiles/semantic/gh8244_01.php"); + } + + public void testGH8244_02() throws Exception { + checkSemantic("testfiles/semantic/gh8244_02.php"); + } }