diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index b8f8783555..6e9c2184a5 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,9 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* java-bestpractices + * [#3542](https://github.com/pmd/pmd/issues/3542): \[java] MissingOverride: False negative for enum method + ### API Changes ### External Contributions diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java index 65c797ad0d..3f5ee53c3e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java @@ -19,7 +19,7 @@ import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName; * * */ -public class ASTEnumConstant extends AbstractJavaNode implements JavaQualifiableNode { +public class ASTEnumConstant extends AbstractJavaTypeNode implements JavaQualifiableNode { private JavaTypeQualifiedName qualifiedName; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java index ea081b8e67..3b4d3736b3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java @@ -86,15 +86,14 @@ public class MissingOverrideRule extends AbstractJavaRule { @Override public Object visit(ASTEnumConstant node, Object data) { - // FIXME, ASTEnumConstant needs typeres support! - // if (node.isAnonymousClass()) { - // currentExploredClass.push(node.getType()); - // } + if (node.isAnonymousClass()) { + currentLookup.push(getMethodLookup(node.getType())); + } super.visit(node, data); - // if (node.isAnonymousClass()) { - // currentExploredClass.pop(); - // } + if (node.isAnonymousClass()) { + currentLookup.pop(); + } return data; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index 560978550a..9a813dbf2e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -40,6 +40,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement; import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral; import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; import net.sourceforge.pmd.lang.java.ast.ASTCastExpression; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; @@ -48,6 +49,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTEnumConstant; +import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression; import net.sourceforge.pmd.lang.java.ast.ASTExclusiveOrExpression; import net.sourceforge.pmd.lang.java.ast.ASTExpression; @@ -258,6 +260,26 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter implements Nulla return data; } + @Override + public Object visit(ASTEnumConstant node, Object data) { + super.visit(node, data); + + if (node.getNumChildren() > 0 && node.getFirstChildOfType(ASTClassOrInterfaceBody.class) != null) { + ASTEnumDeclaration enumDecl = (ASTEnumDeclaration) node.getParent().getParent(); + int clazznumber = node.getIndexInParent() + 1; + JavaTypeDefinition enumType = enumDecl.getTypeDefinition(); + + if (enumType != null) { + String constantType = enumType.getType().getName() + "$" + clazznumber; + Class enumConstantClass = pmdClassLoader.loadClassOrNull(constantType); + if (enumConstantClass != null) { + node.setTypeDefinition(JavaTypeDefinition.forClass(enumConstantClass)); + } + } + } + return data; + } + @Override public Object visit(ASTClassOrInterfaceType node, Object data) { super.visit(node, data); @@ -265,7 +287,7 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter implements Nulla String typeName = node.getImage(); if (node.isAnonymousClass()) { - QualifiableNode parent = node.getFirstParentOfAnyType(ASTAllocationExpression.class, ASTEnumConstant.class); + QualifiableNode parent = node.getFirstParentOfType(ASTAllocationExpression.class); if (parent != null) { typeName = parent.getQualifiedName().toString(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumToString.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumToString.java new file mode 100644 index 0000000000..ab3f6d0d9b --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumToString.java @@ -0,0 +1,28 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.bestpractices.missingoverride; + +public enum EnumToString { + sub_EnumClazz { + // missing @Override + public String toString() { + return "test"; + } + + // missing @Override + public void notOverride() { + System.out.println("test"); + } + }; + + // missing @Override + public String toString() { + return "test"; + } + + public void notOverride() { + System.out.println("test"); + } +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumWithAnonClass.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumWithAnonClass.java index 62268dc324..04b00abecd 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumWithAnonClass.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumWithAnonClass.java @@ -10,15 +10,18 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices.missingoverride; */ public enum EnumWithAnonClass { Foo { - @Override + // missing + public String toString() { + return super.toString(); + } + + // missing public String getSomething() { return null; } }; - public Object getSomething() { return null; } - } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml index 7b12a278ea..99ec5fd4aa 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml @@ -202,17 +202,13 @@ public class ConcreteClassArrayParams extends AbstractClass { ]]> - - Consider enum anon class - 1 - 10 + + Consider enum anon class (#3542) + 2 + 6,11 java 16 + + + [java] MissingOverride: False negative for enum method #3542 + 3 + 6,11,17 + +