diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceType.java index 9cca41b798..05c6e7f6b6 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceType.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceType.java @@ -5,6 +5,8 @@ package net.sourceforge.pmd.lang.java.ast; +import java.util.List; + public class ASTClassOrInterfaceType extends AbstractJavaTypeNode { public ASTClassOrInterfaceType(int id) { super(id); @@ -14,11 +16,35 @@ public class ASTClassOrInterfaceType extends AbstractJavaTypeNode { super(p, id); } - /** * Accept the visitor. * */ public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + /** + * Checks whether the type this node is referring to is declared + * within the same compilation unit - either a class/interface or a enum type. + * You want to check this, if {@link #getType()} is null. + * + * @return true if this node referencing a type in the same compilation unit, + * false otherwise. + */ + public boolean isReferenceToClassSameCompilationUnit() { + ASTCompilationUnit root = getFirstParentOfType(ASTCompilationUnit.class); + List classes = root.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class); + for (ASTClassOrInterfaceDeclaration c : classes) { + if (c.hasImageEqualTo(getImage())) { + return true; + } + } + List enums = root.findDescendantsOfType(ASTEnumDeclaration.class); + for (ASTEnumDeclaration e : enums) { + if (e.hasImageEqualTo(getImage())) { + return true; + } + } + return false; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java index fcef6e33f9..4c8bee843a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java @@ -126,8 +126,9 @@ public class CloseResourceRule extends AbstractJavaRule { if (ref.jjtGetChild(0) instanceof ASTClassOrInterfaceType) { ASTClassOrInterfaceType clazz = (ASTClassOrInterfaceType) ref.jjtGetChild(0); - if (clazz.getType() != null && types.contains(clazz.getType().getName()) || clazz.getType() == null - && simpleTypes.contains(toSimpleType(clazz.getImage())) || types.contains(clazz.getImage())) { + if (clazz.getType() != null && types.contains(clazz.getType().getName()) + || clazz.getType() == null && simpleTypes.contains(toSimpleType(clazz.getImage())) && !clazz.isReferenceToClassSameCompilationUnit() + || types.contains(clazz.getImage()) && !clazz.isReferenceToClassSameCompilationUnit()) { ASTVariableDeclaratorId id = var.getFirstDescendantOfType(ASTVariableDeclaratorId.class); ids.add(id); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index 7c99a9dbf5..b85b962fd4 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -7,12 +7,17 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.List; import org.jaxen.JaxenException; +import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.LanguageVersionHandler; +import net.sourceforge.pmd.lang.Parser; +import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.JavaLanguageModule; import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral; @@ -120,6 +125,27 @@ public class ClassTypeResolverTest { assertEquals(theInnerClass, formalParameter.getTypeNode().getType()); } + /** + * If we don't have the auxclasspath, we might not find the inner class. In that case, + * we'll need to search by name for a match. + * @throws Exception + */ + @Test + public void testInnerClassNotCompiled() throws Exception { + LanguageVersion language = LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getDefaultVersion(); + LanguageVersionHandler languageHandler = language.getLanguageVersionHandler(); + Parser parser = languageHandler.getParser(languageHandler.getDefaultParserOptions()); + Node acu = parser.parse("test", new StringReader("public class TestInnerClass {\n" + + " public void foo() {\n" + + " Statement statement = new Statement();\n" + + " }\n" + + " static class Statement {\n" + + " }\n" + + "}")); + ASTClassOrInterfaceType statement = acu.getFirstDescendantOfType(ASTClassOrInterfaceType.class); + Assert.assertTrue(statement.isReferenceToClassSameCompilationUnit()); + } + @Test public void testAnonymousInnerClass() throws ClassNotFoundException { ASTCompilationUnit acu = parseAndTypeResolveForClass15(AnonymousInnerClass.class); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CloseResource.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CloseResource.xml index 916bcd9ce3..301690ffba 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CloseResource.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CloseResource.xml @@ -652,6 +652,22 @@ public class CloseResource { stmt.close(); } } +} + ]]> + + + + #1479 CloseResource false positive on Statement + 0 + diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 2c872563c3..27613f65a4 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -14,6 +14,8 @@ **Bugfixes:** +* java-design/CloseResource + * [#1479](https://sourceforge.net/p/pmd/bugs/1479/): CloseResource false positive on Statement * java-unusedcode/UnusedLocalVariable * [#1484](https://sourceforge.net/p/pmd/bugs/1484/): UnusedLocalVariable - false positive - parenthesis * java-unusedcode/UnusedModifier