diff --git a/pmd/etc/changelog.txt b/pmd/etc/changelog.txt index 7c79088626..2a8da4c170 100644 --- a/pmd/etc/changelog.txt +++ b/pmd/etc/changelog.txt @@ -412,6 +412,8 @@ Fixed bug 1556594 - Wonky detection of NullAssignment Fixed bug 1481051 - false + UnusedNullCheckInEquals (and other false positives too) Fixed bug 1943204 - Ant task: path should be relative to Ant basedir Fixed patch 2075906 - Add toString() to the rule UnnecessaryWrapperObjectCreation +Fixed bug 2338341 - ArrayIndexOutOfBoundsException in cpd on rails project +Fixed bug 2315623 - @SuppressWarnings("PMD.UseSingleton") has no effect ruleset.dtd and ruleset_xml_schema.xsd added to jar file in rulesets directory bin and java14/bin scripts: retroweaver version was not correct in java14/bin scripts diff --git a/pmd/regress/test/net/sourceforge/pmd/SuppressWarningsTest.java b/pmd/regress/test/net/sourceforge/pmd/SuppressWarningsTest.java index c416900196..cd02ccd72a 100644 --- a/pmd/regress/test/net/sourceforge/pmd/SuppressWarningsTest.java +++ b/pmd/regress/test/net/sourceforge/pmd/SuppressWarningsTest.java @@ -1,12 +1,13 @@ package test.net.sourceforge.pmd; - - import static org.junit.Assert.assertEquals; + +import static org.junit.Assert.assertEquals; import junit.framework.JUnit4TestAdapter; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.Report; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; @@ -15,23 +16,48 @@ import org.junit.Test; import test.net.sourceforge.pmd.testframework.RuleTst; public class SuppressWarningsTest extends RuleTst { - - private static class FooRule extends AbstractJavaRule { - public Object visit(ASTClassOrInterfaceDeclaration c, Object ctx) { - if (c.getImage().equalsIgnoreCase("Foo")) addViolation(ctx, c); - return super.visit(c, ctx); - } - - public Object visit(ASTVariableDeclaratorId c, Object ctx) { - if (c.getImage().equalsIgnoreCase("Foo")) addViolation(ctx, c); - return super.visit(c, ctx); - } - public String getName() { - return "NoFoo"; - } + private static class FooRule extends AbstractJavaRule { + @Override + public Object visit(ASTClassOrInterfaceDeclaration c, Object ctx) { + if (c.getImage().equalsIgnoreCase("Foo")) { + addViolation(ctx, c); + } + return super.visit(c, ctx); + } + + @Override + public Object visit(ASTVariableDeclaratorId c, Object ctx) { + if (c.getImage().equalsIgnoreCase("Foo")) { + addViolation(ctx, c); + } + return super.visit(c, ctx); + } + + @Override + public String getName() { + return "NoFoo"; + } } - + + private static class BarRule extends AbstractJavaRule { + @Override + public Object visit(ASTCompilationUnit cu, Object ctx) { + // Convoluted rule to make sure the violation is reported for the ASTCompilationUnit node + for (ASTClassOrInterfaceDeclaration c : cu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class)) { + if (c.getImage().equalsIgnoreCase("bar")) { + addViolation(ctx, cu); + } + } + return super.visit(cu, ctx); + } + + @Override + public String getName() { + return "NoBar"; + } + } + @Test public void testClassLevelSuppression() throws Throwable { Report rpt = new Report(); @@ -40,63 +66,63 @@ import test.net.sourceforge.pmd.testframework.RuleTst; runTestFromString(TEST2, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(0, rpt.size()); } - + @Test public void testInheritedSuppression() throws Throwable { Report rpt = new Report(); runTestFromString(TEST3, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(0, rpt.size()); } - + @Test public void testMethodLevelSuppression() throws Throwable { Report rpt = new Report(); runTestFromString(TEST4, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(1, rpt.size()); } - + @Test public void testConstructorLevelSuppression() throws Throwable { Report rpt = new Report(); runTestFromString(TEST5, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(0, rpt.size()); } - + @Test public void testFieldLevelSuppression() throws Throwable { Report rpt = new Report(); runTestFromString(TEST6, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(1, rpt.size()); } - + @Test public void testParameterLevelSuppression() throws Throwable { Report rpt = new Report(); runTestFromString(TEST7, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(1, rpt.size()); } - + @Test public void testLocalVariableLevelSuppression() throws Throwable { Report rpt = new Report(); runTestFromString(TEST8, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(1, rpt.size()); } - + @Test public void testSpecificSuppression() throws Throwable { Report rpt = new Report(); runTestFromString(TEST9, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(1, rpt.size()); } - + @Test public void testNoSuppressionBlank() throws Throwable { Report rpt = new Report(); runTestFromString(TEST10, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(2, rpt.size()); } - + @Test public void testNoSuppressionSomethingElseS() throws Throwable { Report rpt = new Report(); @@ -110,11 +136,18 @@ import test.net.sourceforge.pmd.testframework.RuleTst; runTestFromString(TEST12, new FooRule(), rpt, LanguageVersion.JAVA_15); assertEquals(0, rpt.size()); } - + + @Test + public void testSpecificSuppressionAtTopLevel() throws Throwable { + Report rpt = new Report(); + runTestFromString(TEST13, new BarRule(), rpt, LanguageVersion.JAVA_15); + assertEquals(0, rpt.size()); + } + private static final String TEST1 = "@SuppressWarnings(\"PMD\")" + PMD.EOL + "public class Foo {}"; - + private static final String TEST2 = "@SuppressWarnings(\"PMD\")" + PMD.EOL + "public class Foo {" + PMD.EOL + @@ -122,7 +155,7 @@ import test.net.sourceforge.pmd.testframework.RuleTst; " int foo;" + PMD.EOL + " }" + PMD.EOL + "}"; - + private static final String TEST3 = "public class Baz {" + PMD.EOL + " @SuppressWarnings(\"PMD\")" + PMD.EOL + @@ -132,7 +165,7 @@ import test.net.sourceforge.pmd.testframework.RuleTst; " }" + PMD.EOL + " }" + PMD.EOL + "}"; - + private static final String TEST4 = "public class Foo {" + PMD.EOL + " @SuppressWarnings(\"PMD\")" + PMD.EOL + @@ -140,7 +173,7 @@ import test.net.sourceforge.pmd.testframework.RuleTst; " int foo;" + PMD.EOL + " }" + PMD.EOL + "}"; - + private static final String TEST5 = "public class Bar {" + PMD.EOL + " @SuppressWarnings(\"PMD\")" + PMD.EOL + @@ -148,7 +181,7 @@ import test.net.sourceforge.pmd.testframework.RuleTst; " int foo;" + PMD.EOL + " }" + PMD.EOL + "}"; - + private static final String TEST6 = "public class Bar {" + PMD.EOL + " @SuppressWarnings(\"PMD\")" + PMD.EOL + @@ -157,13 +190,13 @@ import test.net.sourceforge.pmd.testframework.RuleTst; " int foo;" + PMD.EOL + " }" + PMD.EOL + "}"; - + private static final String TEST7 = "public class Bar {" + PMD.EOL + " int foo;" + PMD.EOL + " void bar(@SuppressWarnings(\"PMD\") int foo) {}" + PMD.EOL + "}"; - + private static final String TEST8 = "public class Bar {" + PMD.EOL + " int foo;" + PMD.EOL + @@ -171,7 +204,7 @@ import test.net.sourceforge.pmd.testframework.RuleTst; " @SuppressWarnings(\"PMD\") int foo;" + PMD.EOL + " }" + PMD.EOL + "}"; - + private static final String TEST9 = "public class Bar {" + PMD.EOL + " int foo;" + PMD.EOL + @@ -201,9 +234,14 @@ import test.net.sourceforge.pmd.testframework.RuleTst; " @SuppressWarnings(\"all\") int foo;" + PMD.EOL + "}"; + private static final String TEST13 = + "@SuppressWarnings(\"PMD.NoBar\")" + PMD.EOL + + "public class Bar {" + PMD.EOL + + "}"; + public static junit.framework.Test suite() { return new JUnit4TestAdapter(SuppressWarningsTest.class); } } - + diff --git a/pmd/src/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java b/pmd/src/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java index ff38502029..1bcf46cc40 100644 --- a/pmd/src/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java +++ b/pmd/src/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java @@ -11,6 +11,7 @@ import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; @@ -81,6 +82,9 @@ public class JavaRuleViolation extends AbstractRuleViolation { parentTypes.addAll(node.getParentsOfType(ASTClassOrInterfaceBodyDeclaration.class)); parentTypes.addAll(node.getParentsOfType(ASTFormalParameter.class)); parentTypes.addAll(node.getParentsOfType(ASTLocalVariableDeclaration.class)); + if (node instanceof ASTCompilationUnit) { + parentTypes.addAll(node.findChildrenOfType(ASTTypeDeclaration.class)); + } for (Node parentType : parentTypes) { CanSuppressWarnings t = (CanSuppressWarnings) parentType; if (t.hasSuppressWarningsAnnotationFor(getRule())) {