diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedPrivateFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedPrivateFieldRule.java index 823c4a94d1..3ab7f479ee 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedPrivateFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedPrivateFieldRule.java @@ -4,15 +4,21 @@ package net.sourceforge.pmd.lang.java.rule.unusedcode; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTAnnotation; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; 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.ASTEnumBody; import net.sourceforge.pmd.lang.java.ast.ASTEnumConstant; import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; @@ -26,14 +32,44 @@ import net.sourceforge.pmd.lang.symboltable.NameOccurrence; public class UnusedPrivateFieldRule extends AbstractJavaRule { + private boolean lombokImported = false; + private static final String LOMBOK_PACKAGE = "lombok"; + private static final Set LOMBOK_ANNOTATIONS = new HashSet(); + static { + LOMBOK_ANNOTATIONS.add("Data"); + LOMBOK_ANNOTATIONS.add("Getter"); + LOMBOK_ANNOTATIONS.add("Setter"); + LOMBOK_ANNOTATIONS.add("Value"); + LOMBOK_ANNOTATIONS.add("RequiredArgsConstructor"); + LOMBOK_ANNOTATIONS.add("AllArgsConstructor"); + LOMBOK_ANNOTATIONS.add("Builder"); + } + + @Override + public Object visit(ASTCompilationUnit node, Object data) { + lombokImported = false; + return super.visit(node, data); + } + + @Override + public Object visit(ASTImportDeclaration node, Object data) { + ASTName name = node.getFirstChildOfType(ASTName.class); + if (!lombokImported && name != null && name.getImage() != null & name.getImage().startsWith(LOMBOK_PACKAGE)) { + lombokImported = true; + } + return super.visit(node, data); + } + @Override public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { + boolean classHasLombok = hasLombokAnnotation(node); + Map> vars = node.getScope().getDeclarations( VariableNameDeclaration.class); for (Map.Entry> entry : vars.entrySet()) { VariableNameDeclaration decl = entry.getKey(); AccessNode accessNodeParent = decl.getAccessNodeParent(); - if (!accessNodeParent.isPrivate() || isOK(decl.getImage())) { + if (!accessNodeParent.isPrivate() || isOK(decl.getImage()) || classHasLombok || hasLombokAnnotation(accessNodeParent)) { continue; } if (!actuallyUsed(entry.getValue())) { @@ -45,6 +81,31 @@ public class UnusedPrivateFieldRule extends AbstractJavaRule { return super.visit(node, data); } + private boolean hasLombokAnnotation(Node node) { + boolean result = false; + Node parent = node.jjtGetParent(); + List annotations = parent.findChildrenOfType(ASTAnnotation.class); + for (ASTAnnotation annotation : annotations) { + ASTName name = annotation.getFirstDescendantOfType(ASTName.class); + if (name != null) { + String annotationName = name.getImage(); + if (lombokImported) { + if (LOMBOK_ANNOTATIONS.contains(annotationName)) { + result = true; + } + } else { + if (annotationName.startsWith(LOMBOK_PACKAGE + ".")) { + String shortName = annotationName.substring(LOMBOK_PACKAGE.length() + 1); + if (LOMBOK_ANNOTATIONS.contains(shortName)) { + result = true; + } + } + } + } + } + return result; + } + private boolean usedInOuterEnum(ASTClassOrInterfaceDeclaration node, NameDeclaration decl) { List outerEnums = node.getParentsOfType(ASTEnumDeclaration.class); for (ASTEnumDeclaration outerEnum : outerEnums) { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/unusedcode/xml/UnusedPrivateField.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/unusedcode/xml/UnusedPrivateField.xml index 8cf17b064f..6db6f5e73e 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/unusedcode/xml/UnusedPrivateField.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/unusedcode/xml/UnusedPrivateField.xml @@ -459,6 +459,80 @@ public class UnusedPrivateFieldClass return m_bugTest.m_number == m_number; } } +} + ]]> + + + + #1420 UnusedPrivateField: Ignore fields if using lombok - 1 + 0 + + + + #1420 UnusedPrivateField: Ignore fields if using lombok - 2 + 0 + + + + #1420 UnusedPrivateField: Ignore fields if using lombok - 3 + 0 + + + + #1420 UnusedPrivateField: Ignore fields if using lombok - 4 + 0 + + + + #1420 UnusedPrivateField: Ignore fields if using lombok - 5 + 0 + + + + #1420 UnusedPrivateField: Ignore fields if using lombok - 6 + 0 + + + + #1420 UnusedPrivateField: Ignore fields if using lombok - 7 + 1 + diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 4b3ad93c29..2ab3653660 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -15,7 +15,7 @@ PMD and CPD Command Line Interfaces have a new optional parameter: `failOnViolation`. Executing PMD with the option `-failOnViolation false` will perform the PMD checks but won't fail the build and still exit with status 0. This is useful if you only want to generate the report with violations but don't want to fail your build. - +* [#1420](https://sourceforge.net/p/pmd/bugs/1420/): UnusedPrivateField: Ignore fields if using lombok **New Rules:** @@ -57,6 +57,8 @@ assertEquals, that use Boolean.TRUE/FALSE constants. * Modified Rule: rulesets/java/basic.xml/CheckResultSet: Do not require to check the result of a navigation method, if it is returned. +* Modified Rule: rulesets/java/unusedcode.xml/UnusedPrivateField: This rule won't trigger anymore if + [Lombok](https://projectlombok.org) is in use. See [#1420](https://sourceforge.net/p/pmd/bugs/1420/). **Pull Requests:**