diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index bea0b9843c..623db93b71 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -23,6 +23,8 @@ This is a {{ site.pmd.release_type }} release. * java * [#1861](https://github.com/pmd/pmd/issues/1861): \[java] Be more lenient with version numbers * [#2105](https://github.com/pmd/pmd/issues/2105): \[java] Wrong name for inner classes in violations +* java-design + * [#2075](https://github.com/pmd/pmd/issues/2075): \[java] ImmutableField false positive with inner class ### API Changes diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java index a4385b640f..708b82696f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java @@ -60,7 +60,7 @@ public class ImmutableFieldRule extends AbstractLombokAwareRule { continue; } - FieldImmutabilityType type = initializedInConstructor(entry.getValue(), new HashSet<>(constructors)); + FieldImmutabilityType type = initializedInConstructor(field, entry.getValue(), new HashSet<>(constructors)); if (type == FieldImmutabilityType.MUTABLE) { continue; } @@ -75,7 +75,7 @@ public class ImmutableFieldRule extends AbstractLombokAwareRule { return field.getAccessNodeParent().hasDescendantOfType(ASTVariableInitializer.class); } - private FieldImmutabilityType initializedInConstructor(List usages, Set allConstructors) { + private FieldImmutabilityType initializedInConstructor(VariableNameDeclaration field, List usages, Set allConstructors) { FieldImmutabilityType result = FieldImmutabilityType.MUTABLE; int methodInitCount = 0; int lambdaUsage = 0; @@ -85,7 +85,7 @@ public class ImmutableFieldRule extends AbstractLombokAwareRule { if (jocc.isOnLeftHandSide() || jocc.isSelfAssignment()) { Node node = jocc.getLocation(); ASTConstructorDeclaration constructor = node.getFirstParentOfType(ASTConstructorDeclaration.class); - if (constructor != null) { + if (constructor != null && isSameClass(field, constructor)) { if (inLoopOrTry(node)) { continue; } @@ -124,6 +124,14 @@ public class ImmutableFieldRule extends AbstractLombokAwareRule { return result; } + /** + * Checks whether the given constructor belongs to the class, in which the field is declared. + * This might not be the case for inner classes, which accesses the fields of the outer class. + */ + private boolean isSameClass(VariableNameDeclaration field, ASTConstructorDeclaration constructor) { + return constructor.getFirstParentOfType(ASTClassOrInterfaceBody.class) == field.getNode().getFirstParentOfType(ASTClassOrInterfaceBody.class); + } + private boolean inLoopOrTry(Node node) { return node.getFirstParentOfType(ASTTryStatement.class) != null || node.getFirstParentOfType(ASTForStatement.class) != null diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml index dfdad47f50..7739b840c1 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml @@ -496,6 +496,35 @@ public class Foo { public Foo() { x = "bar"; } +} + ]]> + + + + #2075 [java] ImmutableField false positive with inner class + 0 +