Merge branch 'fp-unnecessary-modifier-enum'

This commit is contained in:
Juan Martín Sotuyo Dodero
2018-06-12 00:52:07 -03:00
6 changed files with 299 additions and 63 deletions

View File

@ -13,12 +13,19 @@ This is a minor release.
### Table Of Contents
* [New and noteworthy](#new-and-noteworthy)
* [Modified Rules](#modified-rules)
* [Fixed Issues](#fixed-issues)
* [API Changes](#api-changes)
* [External Contributions](#external-contributions)
### New and noteworthy
#### Modified Rules
* The Java rule [UnnecessaryModifier](pmd_rules_java_codestyle.html#unnecessarymodifier) (`java-codestyle`)
now detects enum constrcutors with explicit `private` modifier. The rule now produces better error messages
letting you know exactly which modifiers are redundant at each declaration.
### Fixed Issues
* all

View File

@ -6,7 +6,7 @@
package net.sourceforge.pmd.lang.java.ast;
public class ASTAnnotationMethodDeclaration extends AbstractJavaAccessNode {
public class ASTAnnotationMethodDeclaration extends AbstractMethodLikeNode {
public ASTAnnotationMethodDeclaration(int id) {
super(id);
}
@ -19,6 +19,12 @@ public class ASTAnnotationMethodDeclaration extends AbstractJavaAccessNode {
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
@Override
public MethodLikeKind getKind() {
return MethodLikeKind.METHOD;
}
}
/*
* JavaCC - OriginalChecksum=f6dd440446f8aa5c9c191ae760080ee0 (do not edit this

View File

@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
@ -26,9 +27,6 @@ public abstract class AbstractAnyTypeDeclaration extends AbstractJavaAccessTypeN
}
/**
* Returns true if this type declaration is nested inside an interface, class or annotation.
*/
@Override
public final boolean isNested() {
return jjtGetParent() instanceof ASTClassOrInterfaceBodyDeclaration
@ -36,6 +34,46 @@ public abstract class AbstractAnyTypeDeclaration extends AbstractJavaAccessTypeN
}
/**
* Returns true if the enclosing type of this type declaration
* is any of the given kinds. If this declaration is a top-level
* declaration, returns false. This won't consider anonymous classes
* until #905 is tackled. TODO 7.0.0
*
* @param kinds Kinds to test
*/
// TODO 7.0.0 move that up to ASTAnyTypeDeclaration
public final boolean enclosingTypeIsA(TypeKind... kinds) {
ASTAnyTypeDeclaration parent = getEnclosingTypeDeclaration();
if (parent == null) {
return false;
}
for (TypeKind k : kinds) {
if (parent.getTypeKind() == k) {
return true;
}
}
return false;
}
/**
* Returns the enclosing type of this type, if it is nested.
* Otherwise returns null. This won't consider anonymous classes
* until #905 is tackled. TODO 7.0.0
*/
public final ASTAnyTypeDeclaration getEnclosingTypeDeclaration() {
if (!isNested()) {
return null;
}
Node parent = getNthParent(3);
return parent instanceof ASTAnyTypeDeclaration ? (ASTAnyTypeDeclaration) parent : null;
}
@Override
public final JavaTypeQualifiedName getQualifiedName() {
return qualifiedName;

View File

@ -1634,7 +1634,7 @@ public class Foo {
<rule name="UnnecessaryModifier"
language="java"
since="1.02"
message="Avoid modifiers which are implied by the context"
message="Unnecessary modifier{0} on {1} ''{2}''{3}"
class="net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryModifierRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#unnecessarymodifier">
<description>

View File

@ -195,6 +195,10 @@ public class Foo {
Unneeded 'public static final' in interface field inside another interface
]]></description>
<expected-problems>2</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'public' on interface 'Bar': members of interface types are implicitly public</message>
<message>Unnecessary modifiers 'public static final' on field 'X': the field is declared in an interface type</message>
</expected-messages>
<code><![CDATA[
public interface Foo {
public interface Bar {
@ -205,6 +209,23 @@ public interface Foo {
</test-code>
<test-code>
<description><![CDATA[
Unneeded 'public static final' in annotation field inside another interface
]]></description>
<expected-problems>2</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'public' on annotation 'Bar': members of interface types are implicitly public</message>
<message>Unnecessary modifiers 'public static final' on field 'X': the field is declared in an annotation type</message>
</expected-messages>
<code><![CDATA[
public interface Foo {
public @interface Bar {
public static final int X = 0;
}
}
]]></code>
</test-code>
<test-code>
<description><![CDATA[
OK in interface field inside another interface
]]></description>
<expected-problems>0</expected-problems>
@ -303,6 +324,9 @@ public enum TestEnum {
<test-code>
<description>Unnecessary public on annotation element</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'public' on method 'message': the method is declared in an annotation type</message>
</expected-messages>
<code><![CDATA[
public @interface TestAnnotation {
public String message();
@ -312,6 +336,9 @@ public @interface TestAnnotation {
<test-code>
<description>Unnecessary abstract on annotation element</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'abstract' on method 'message': the method is declared in an annotation type</message>
</expected-messages>
<code><![CDATA[
public @interface TestAnnotation {
abstract String message();
@ -387,7 +414,11 @@ public @interface TestAnnotation {
</test-code>
<test-code>
<description>Unnecessary static on annotation nested enum</description>
<expected-problems>1</expected-problems>
<expected-problems>2</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'public' on enum 'Inner': the enum is declared in an annotation type</message>
<message>Unnecessary modifier 'static' on enum 'Inner': nested enums are implicitly static</message>
</expected-messages>
<code><![CDATA[
public @interface TestAnnotation {
public static enum Inner {
@ -397,7 +428,11 @@ public @interface TestAnnotation {
</test-code>
<test-code>
<description>Unnecessary static on interface nested enum</description>
<expected-problems>1</expected-problems>
<expected-problems>2</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'public' on enum 'Inner': the enum is declared in an interface type</message>
<message>Unnecessary modifier 'static' on enum 'Inner': nested enums are implicitly static</message>
</expected-messages>
<code><![CDATA[
public interface TestInterface {
public static enum Inner {
@ -408,6 +443,9 @@ public interface TestInterface {
<test-code>
<description>Unnecessary static on class nested enum</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'static' on enum 'Inner': nested enums are implicitly static</message>
</expected-messages>
<code><![CDATA[
public class TestClass {
public static enum Inner {
@ -418,6 +456,9 @@ public class TestClass {
<test-code>
<description>Unnecessary abstract on interface</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'abstract' on interface 'TestInterface': interface types are implicitly abstract</message>
</expected-messages>
<code><![CDATA[
public abstract interface TestInterface {
}
@ -426,6 +467,9 @@ public abstract interface TestInterface {
<test-code>
<description>Unnecessary abstract on annotation</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'abstract' on annotation 'TestAnnotation': annotations types are implicitly abstract</message>
</expected-messages>
<code><![CDATA[
public abstract @interface TestAnnotation {
}
@ -443,9 +487,7 @@ public class Foo {
]]></code>
</test-code>
<test-code>
<description><![CDATA[
final and non-final methods mixed
]]></description>
<description>final and non-final methods mixed</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@ -459,6 +501,9 @@ public class Foo {
final method on a final class
]]></description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'final' on method 'foo': the method is already in a final class</message>
</expected-messages>
<code><![CDATA[
public final class Foo {
public final void foo() { }
@ -470,6 +515,9 @@ public final class Foo {
mixed final and non-final methods on final class
]]></description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'final' on method 'foo': the method is already in a final class</message>
</expected-messages>
<code><![CDATA[
public final class Foo {
public final void foo() { }
@ -509,6 +557,9 @@ public final class Foo {
final method in inner final class
]]></description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'final' on method 'buz': the method is already in a final class</message>
</expected-messages>
<code><![CDATA[
public final class Foo {
public final class Bar {
@ -539,6 +590,9 @@ public final class InboxContents2 {
<test-code>
<description>Unnecessary final of private method</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'final' on method 'getValue': private methods cannot be overridden</message>
</expected-messages>
<code><![CDATA[
public class TestClass {
private final int getValue() {
@ -550,6 +604,9 @@ public class TestClass {
<test-code>
<description>Unnecessary final of enum method</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'final' on method 'magic': an anonymous class cannot be extended</message>
</expected-messages>
<code><![CDATA[
public enum Foo {
BAR {
@ -578,6 +635,9 @@ public class Foo {
<test-code>
<description>Unnecessary final of try-with-resources resource</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'final' on resource specification 'fw': resource specifications are implicitly final</message>
</expected-messages>
<code><![CDATA[
public class Foo {
public void stuff() {
@ -595,6 +655,24 @@ public class Foo {
class Foo {
@Bar
final void method() { }
}
]]></code>
</test-code>
<test-code>
<description>Private constructor of enum</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'private' on constructor 'Foo(String)': enum constructors are implicitly private</message>
</expected-messages>
<code><![CDATA[
enum Foo {
BAR("bar");
private String name;
private Foo(String s) {
name = s;
}
}
]]></code>
</test-code>