diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java index f845839b70..1a01094244 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java @@ -14,6 +14,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; import net.sourceforge.pmd.lang.java.ast.ASTInitializer; +import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; @@ -119,6 +120,12 @@ public class SingularFieldRule extends AbstractLombokAwareRule { break; // Optimization } + if (location.getFirstParentOfType(ASTLambdaExpression.class) != null) { + // This usage is inside a lambda expression + violation = false; + break; // Optimization + } + Node method = location.getFirstParentOfType(ASTMethodDeclaration.class); if (method == null) { method = location.getFirstParentOfType(ASTConstructorDeclaration.class); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SingularField.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SingularField.xml index 626a48c15c..0b9495bc1d 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SingularField.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SingularField.xml @@ -569,4 +569,40 @@ public class MyClass { } ]]> + + + + #177 [java] SingularField with lambdas as final fields + 0 + { + // do nothing for now + }); + this.timer2 = new Timer(0, e -> { + // do nothing for now + }); + } + + /** Use a lambda expression to reference timer1 -- triggers SingularField error. */ + private final Runnable play1 = () -> { + this.timer1.start(); + }; + + /** Use an anonymous class to reference timer2 -- no error. */ + private final Runnable play2 = new Runnable() { + @Override + public void run() { + this.timer2.start(); + } + }; +} + ]]> + diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 57efcc91aa..21080c369a 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -223,6 +223,7 @@ to avoid XSS attacks. * java-design * [#1512](https://sourceforge.net/p/pmd/bugs/1512/): \[java] Combine rules AvoidConstantsInInterface and ConstantsInInterface * [#1552](https://sourceforge.net/p/pmd/bugs/1552/): \[java] MissingBreakInSwitch - False positive for continue + * [#177](https://github.com/pmd/pmd/issues/177): \[java] SingularField with lambdas as final fields * java-imports * [#1546](https://sourceforge.net/p/pmd/bugs/1546/): \[java] UnnecessaryFullyQualifiedNameRule doesn't take into consideration conflict resolution * [#1547](https://sourceforge.net/p/pmd/bugs/1547/): \[java] UnusedImportRule - False Positive for only usage in Javadoc - {@link ClassName#CONSTANT}