From 8667aea076e5902ffcd58eed789a8316a24f20e1 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 1 Oct 2016 17:45:47 +0200 Subject: [PATCH] Fixes #1529 [java] UnusedImports: The created rule violation has no class name --- .../pmd/lang/java/rule/JavaRuleViolation.java | 19 +++++++- .../lang/java/rule/JavaRuleViolationTest.java | 46 +++++++++++++++++++ src/site/markdown/overview/changelog.md | 2 + 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java index 81ab2cb3a5..4e45b22e54 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java @@ -3,6 +3,8 @@ */ package net.sourceforge.pmd.lang.java.rule; +import java.util.Set; + import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.Node; @@ -13,8 +15,10 @@ import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.java.ast.CanSuppressWarnings; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.symboltable.ClassNameDeclaration; import net.sourceforge.pmd.lang.java.symboltable.ClassScope; import net.sourceforge.pmd.lang.java.symboltable.MethodScope; import net.sourceforge.pmd.lang.java.symboltable.SourceFileScope; @@ -91,7 +95,6 @@ public class JavaRuleViolation extends ParametricRuleViolation { } private void setClassNameFrom(JavaNode node) { - String qualifiedName = null; for (ASTClassOrInterfaceDeclaration parent : node.getParentsOfType(ASTClassOrInterfaceDeclaration.class)) { String clsName = parent.getScope().getEnclosingScope(ClassScope.class).getClassName(); @@ -101,6 +104,20 @@ public class JavaRuleViolation extends ParametricRuleViolation { qualifiedName = clsName + '$' + qualifiedName; } } + + if (qualifiedName == null) { + Set classes = node.getScope().getEnclosingScope(SourceFileScope.class).getClassDeclarations().keySet(); + for (ClassNameDeclaration c : classes) { + // find the first public class/enum declaration + if (c.getAccessNodeParent() instanceof AccessNode) { + if (((AccessNode)c.getAccessNodeParent()).isPublic()) { + qualifiedName = c.getImage(); + break; + } + } + } + } + if (qualifiedName != null) { className = qualifiedName; } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationTest.java index a15f57ea1b..ba065a88c2 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationTest.java @@ -14,6 +14,7 @@ import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.lang.java.JavaLanguageModule; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; +import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.symboltable.ScopeAndDeclarationFinder; @@ -56,4 +57,49 @@ public class JavaRuleViolationTest { final JavaRuleViolation violation = new JavaRuleViolation(null, context, md, null); assertEquals("bar", violation.getMethodName()); } + + /** + * Tests that the class name is taken correctly, even if the node is outside of a class scope, + * e.g. a import declaration. + * @see #1529 + */ + @Test + public void testPackageAndClassName() { + ASTCompilationUnit ast = parse("package pkg; import java.util.List; public class Foo { }"); + ASTImportDeclaration importNode = ast.getFirstDescendantOfType(ASTImportDeclaration.class); + + JavaRuleViolation violation = new JavaRuleViolation(null, new RuleContext(), importNode, null); + assertEquals("pkg", violation.getPackageName()); + assertEquals("Foo", violation.getClassName()); + } + + @Test + public void testPackageAndEnumName() { + ASTCompilationUnit ast = parse("package pkg; import java.util.List; public enum FooE { }"); + ASTImportDeclaration importNode = ast.getFirstDescendantOfType(ASTImportDeclaration.class); + + JavaRuleViolation violation = new JavaRuleViolation(null, new RuleContext(), importNode, null); + assertEquals("pkg", violation.getPackageName()); + assertEquals("FooE", violation.getClassName()); + } + + @Test + public void testDefaultPackageAndClassName() { + ASTCompilationUnit ast = parse("import java.util.List; public class Foo { }"); + ASTImportDeclaration importNode = ast.getFirstDescendantOfType(ASTImportDeclaration.class); + + JavaRuleViolation violation = new JavaRuleViolation(null, new RuleContext(), importNode, null); + assertEquals("", violation.getPackageName()); + assertEquals("Foo", violation.getClassName()); + } + + @Test + public void testPackageAndMultipleClassesName() { + ASTCompilationUnit ast = parse("package pkg; import java.util.List; class Foo { } public class Bar { }"); + ASTImportDeclaration importNode = ast.getFirstDescendantOfType(ASTImportDeclaration.class); + + JavaRuleViolation violation = new JavaRuleViolation(null, new RuleContext(), importNode, null); + assertEquals("pkg", violation.getPackageName()); + assertEquals("Bar", violation.getClassName()); + } } diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index ce55eef7f5..6ac407ab54 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -23,6 +23,8 @@ * [#1522](https://sourceforge.net/p/pmd/bugs/1522/): \[java] CommentRequired: false positive * java-design/CloseResource * [#1479](https://sourceforge.net/p/pmd/bugs/1479/): CloseResource false positive on Statement +* java-imports/UnusedImports + * [#1529](https://sourceforge.net/p/pmd/bugs/1529/): \[java] UnusedImports: The created rule violation has no class name * java-unusedcode/UnusedLocalVariable * [#1484](https://sourceforge.net/p/pmd/bugs/1484/): UnusedLocalVariable - false positive - parenthesis * java-unusedcode/UnusedModifier