This is an automated email from the ASF dual-hosted git repository. tmysik pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push: new 3cc64b4f7c Fix incorrect unused coloring #5551 new 137b7651eb Merge pull request #5670 from junichi11/php-gh-5551-incorrect-unused 3cc64b4f7c is described below commit 3cc64b4f7c706ce5e4875b6e78deeb39da603817 Author: Junichi Yamamoto <junich...@apache.org> AuthorDate: Fri Mar 17 11:24:11 2023 +0900 Fix incorrect unused coloring #5551 When there is an anonymous class in a method body, the anonymous class also removes method blocks of the enclosing class that need to be scanned. So, to prevent that, use `Map<TypeInfo, List<Block>>` instead of `List<Block>` --- .../modules/php/editor/csl/SemanticAnalysis.java | 52 +++++++++++-------- .../unit/data/testfiles/semantic/gh5551_01.php | 51 +++++++++++++++++++ .../data/testfiles/semantic/gh5551_01.php.semantic | 51 +++++++++++++++++++ .../unit/data/testfiles/semantic/gh5551_02.php | 59 ++++++++++++++++++++++ .../data/testfiles/semantic/gh5551_02.php.semantic | 59 ++++++++++++++++++++++ .../php/editor/csl/SemanticAnalyzerTest.java | 8 +++ 6 files changed, 259 insertions(+), 21 deletions(-) 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 dbe9780708..a1aa52130c 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 @@ -227,7 +227,7 @@ public class SemanticAnalysis extends SemanticAnalyzer { // for unsed private method: name, identifier private final Map<UnusedIdentifier, ASTNodeColoring> privateUnusedMethods; // this is holder of blocks, which has to be scanned for usages in the class. - private List<Block> needToScan = new ArrayList<>(); + private final Map<TypeInfo, List<Block>> needToScan = new HashMap<>(); private final Snapshot snapshot; @@ -409,18 +409,16 @@ public class SemanticAnalysis extends SemanticAnalyzer { scan(cldec.getInterfaes()); Identifier name = cldec.getName(); addColoringForNode(name, createTypeNameColoring(name)); - needToScan = new ArrayList<>(); + needToScan.put(typeInfo, new ArrayList<>()); if (cldec.getBody() != null) { cldec.getBody().accept(this); // find all usages in the method bodies - while (!needToScan.isEmpty()) { - Block block = needToScan.remove(0); - block.accept(this); - } + scanMethodBodies(); addColoringForUnusedPrivateConstants(); addColoringForUnusedPrivateFields(); } + needToScan.remove(typeInfo); removeFromPath(); } @@ -515,8 +513,8 @@ public class SemanticAnalysis extends SemanticAnalyzer { // don't scan the body now. It should be scanned after all declarations // are known Block body = md.getFunction().getBody(); - if (body != null) { - needToScan.add(body); + if (body != null && needToScan.get(typeInfo) != null) { + needToScan.get(typeInfo).add(body); } } } @@ -595,23 +593,24 @@ public class SemanticAnalysis extends SemanticAnalyzer { // to avoid recognizing $this as an instance of an anonymous class scan(node.ctorParams()); addToPath(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 = new ArrayList<>(); + needToScan.put(typeInfo, new ArrayList<>()); Block body = node.getBody(); if (body != null) { body.accept(this); // find all usages in the method bodies - while (!needToScan.isEmpty()) { - Block block = needToScan.remove(0); - block.accept(this); - } + scanMethodBodies(); addColoringForUnusedPrivateConstants(); addColoringForUnusedPrivateFields(); } + needToScan.remove(typeInfo); + typeInfo = originalTypeInfo; removeFromPath(); } else { super.visit(node); @@ -639,14 +638,13 @@ public class SemanticAnalysis extends SemanticAnalyzer { typeInfo = new TypeDeclarationTypeInfo(node); Identifier name = node.getName(); addColoringForNode(name, createTypeNameColoring(name)); - needToScan = new ArrayList<>(); + needToScan.put(typeInfo, new ArrayList<>()); if (node.getBody() != null) { node.getBody().accept(this); - for (Block block : needToScan) { - block.accept(this); - } + scanMethodBodies(); addColoringForUnusedPrivateFields(); } + needToScan.remove(typeInfo); removeFromPath(); } @@ -661,13 +659,12 @@ public class SemanticAnalysis extends SemanticAnalyzer { typeInfo = new TypeDeclarationTypeInfo(node); Identifier name = node.getName(); addColoringForNode(name, createTypeNameColoring(name)); - needToScan = new ArrayList<>(); + needToScan.put(typeInfo, new ArrayList<>()); if (node.getBody() != null) { node.getBody().accept(this); - for (Block block : needToScan) { - block.accept(this); - } + scanMethodBodies(); } + needToScan.remove(typeInfo); removeFromPath(); } @@ -991,6 +988,19 @@ public class SemanticAnalysis extends SemanticAnalyzer { super.visit(node); } + /** + * Find all usages in the method bodies. + */ + private void scanMethodBodies() { + if (needToScan.get(typeInfo) == null) { + return; + } + for (Block block : needToScan.get(typeInfo)) { + block.accept(this); + } + needToScan.get(typeInfo).clear(); + } + private class FieldAccessVisitor extends DefaultVisitor { private final Set<ColoringAttributes> coloring; diff --git a/php/php.editor/test/unit/data/testfiles/semantic/gh5551_01.php b/php/php.editor/test/unit/data/testfiles/semantic/gh5551_01.php new file mode 100644 index 0000000000..4c1256e5e3 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/semantic/gh5551_01.php @@ -0,0 +1,51 @@ +<?php +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +class TestClass { + public function testMethod(string $test): string { + return $test; + } +} + +interface TestInterface { + public function testMethod(string $test): string; +} + +class GH5551 { + + private function usedPrivateMethod1(): TestClass { + return new TestClass(); + } + + private function usedPrivateMethod2(): TestInterface { + return new class implements TestInterface { + public function testMethod(string $test): string { + return $test; + } + }; + } + + private function unusedPrivateMethod(): void { + } + + public function test() { + echo $this->usedPrivateMethod1()->testMethod("test1"), PHP_EOL; + echo $this->usedPrivateMethod2()->testMethod("test2"), PHP_EOL; + } +} diff --git a/php/php.editor/test/unit/data/testfiles/semantic/gh5551_01.php.semantic b/php/php.editor/test/unit/data/testfiles/semantic/gh5551_01.php.semantic new file mode 100644 index 0000000000..dbcdcefa6a --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/semantic/gh5551_01.php.semantic @@ -0,0 +1,51 @@ +<?php +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +class |>CLASS:TestClass<| { + public function |>METHOD:testMethod<|(string $test): string { + return $test; + } +} + +interface |>CLASS:TestInterface<| { + public function |>METHOD:testMethod<|(string $test): string; +} + +class |>CLASS:GH5551<| { + + private function |>METHOD:usedPrivateMethod1<|(): TestClass { + return new TestClass(); + } + + private function |>METHOD:usedPrivateMethod2<|(): TestInterface { + return new class implements TestInterface { + public function |>METHOD:testMethod<|(string $test): string { + return $test; + } + }; + } + + private function |>METHOD,UNUSED:unusedPrivateMethod<|(): void { + } + + public function |>METHOD:test<|() { + echo $this->|>CUSTOM1:usedPrivateMethod1<|()->|>CUSTOM1:testMethod<|("test1"), PHP_EOL; + echo $this->|>CUSTOM1:usedPrivateMethod2<|()->|>CUSTOM1:testMethod<|("test2"), PHP_EOL; + } +} diff --git a/php/php.editor/test/unit/data/testfiles/semantic/gh5551_02.php b/php/php.editor/test/unit/data/testfiles/semantic/gh5551_02.php new file mode 100644 index 0000000000..2d7f8cb0d0 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/semantic/gh5551_02.php @@ -0,0 +1,59 @@ +<?php +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +class TestClass { + public function testMethod(string $test): string { + return $test; + } +} + +interface TestInterface { + public function testMethod(string $test): string; +} + +class GH5551 { + + private function usedPrivateMethod1(): TestClass { + return new TestClass(); + } + + private function usedPrivateMethod2(): TestInterface { + return new class implements TestInterface { + + private function unusedPrivateMethod(): void { + } + + private function usedPrivateMethod(): void { + } + + public function testMethod(string $test): string { + $this->usedPrivateMethod(); + return $test; + } + }; + } + + private function unusedPrivateMethod(): void { + } + + public function test() { + echo $this->usedPrivateMethod1()->testMethod("test1"), PHP_EOL; + echo $this->usedPrivateMethod2()->testMethod("test2"), PHP_EOL; + } +} diff --git a/php/php.editor/test/unit/data/testfiles/semantic/gh5551_02.php.semantic b/php/php.editor/test/unit/data/testfiles/semantic/gh5551_02.php.semantic new file mode 100644 index 0000000000..870be797d9 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/semantic/gh5551_02.php.semantic @@ -0,0 +1,59 @@ +<?php +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +class |>CLASS:TestClass<| { + public function |>METHOD:testMethod<|(string $test): string { + return $test; + } +} + +interface |>CLASS:TestInterface<| { + public function |>METHOD:testMethod<|(string $test): string; +} + +class |>CLASS:GH5551<| { + + private function |>METHOD:usedPrivateMethod1<|(): TestClass { + return new TestClass(); + } + + private function |>METHOD:usedPrivateMethod2<|(): TestInterface { + return new class implements TestInterface { + + private function |>METHOD,UNUSED:unusedPrivateMethod<|(): void { + } + + private function |>METHOD:usedPrivateMethod<|(): void { + } + + public function |>METHOD:testMethod<|(string $test): string { + $this->|>CUSTOM1:usedPrivateMethod<|(); + return $test; + } + }; + } + + private function |>METHOD,UNUSED:unusedPrivateMethod<|(): void { + } + + public function |>METHOD:test<|() { + echo $this->|>CUSTOM1:usedPrivateMethod1<|()->|>CUSTOM1:testMethod<|("test1"), PHP_EOL; + echo $this->|>CUSTOM1:usedPrivateMethod2<|()->|>CUSTOM1:testMethod<|("test2"), PHP_EOL; + } +} 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 633e0221b8..f7c50a0cc9 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 @@ -217,4 +217,12 @@ public class SemanticAnalyzerTest extends SemanticAnalysisTestBase { public void testConstantsInTraits() throws Exception { checkSemantic("testfiles/semantic/constantsInTraits.php"); } + + public void testGH5551_01() throws Exception { + checkSemantic("testfiles/semantic/gh5551_01.php"); + } + + public void testGH5551_02() throws Exception { + checkSemantic("testfiles/semantic/gh5551_02.php"); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists