Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[java] UnusedAssignment false positive in record compact constructor #4839

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/pages/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ The rules have been moved into categories with PMD 6.
* [#3751](https://github.com/pmd/pmd/issues/3751): \[java] Rename some node types
* [#4628](https://github.com/pmd/pmd/pull/4628): \[java] Support loading classes from java runtime images
* [#4753](https://github.com/pmd/pmd/issues/4753): \[java] PMD crashes while using generics and wildcards
* java-bestpractives
* java-bestpractices
* [#4603](https://github.com/pmd/pmd/issues/4603): \[java] UnusedAssignment false positive in record compact constructor
* [#4625](https://github.com/pmd/pmd/issues/4625): \[java] UnusedPrivateMethod false positive: Autoboxing into Number
* java-codestyle
* [#2847](https://github.com/pmd/pmd/issues/2847): \[java] New Rule: Use Explicit Types
Expand Down Expand Up @@ -1406,6 +1407,7 @@ Language specific fixes:
* [#4516](https://github.com/pmd/pmd/issues/4516): \[java] UnusedLocalVariable: false-negative with try-with-resources
* [#4517](https://github.com/pmd/pmd/issues/4517): \[java] UnusedLocalVariable: false-negative with compound assignments
* [#4518](https://github.com/pmd/pmd/issues/4518): \[java] UnusedLocalVariable: false-positive with multiple for-loop indices
* [#4603](https://github.com/pmd/pmd/issues/4603): \[java] UnusedAssignment false positive in record compact constructor
* [#4625](https://github.com/pmd/pmd/issues/4625): \[java] UnusedPrivateMethod false positive: Autoboxing into Number
* [#4634](https://github.com/pmd/pmd/issues/4634): \[java] JUnit4TestShouldUseTestAnnotation false positive with TestNG
* java-codestyle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement;
import net.sourceforge.pmd.lang.java.ast.ASTMethodCall;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTRecordComponent;
import net.sourceforge.pmd.lang.java.ast.ASTResourceList;
import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
import net.sourceforge.pmd.lang.java.ast.ASTStatement;
Expand Down Expand Up @@ -818,6 +819,23 @@ public SpanInfo visit(ASTVariableDeclarator node, SpanInfo data) {
return data;
}

@Override
public SpanInfo visit(ASTCompactConstructorDeclaration node, SpanInfo data) {
super.visit(node, data);

// mark any write to a variable that is named like a record component as usage
// record compact constructors do an implicit assignment at the end.
for (ASTRecordComponent component : node.getEnclosingType().getRecordComponents()) {
node.descendants(ASTAssignmentExpression.class)
.descendants(ASTVariableAccess.class)
.filter(v -> v.getAccessType() == AccessType.WRITE)
.filter(v -> v.getName().equals(component.getVarId().getName()))
.forEach(varAccess -> data.use(varAccess.getReferencedSym(), null));
}

return data;
}

/**
* Whether the variable has an implicit initializer, that is not
* an expression. For instance, formal parameters have a value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3543,4 +3543,43 @@ public class UnusedAssignmentUnusedVariableFP {
}
]]></code>
</test-code>

<test-code>
<description>[java] UnusedAssignment false positive in record compact constructor #4603</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Main {
public static void main(String[] args) {
System.out.println(new TestRecord(2).foo());
}
}

record TestRecord(int foo) {
TestRecord {
// src/Main.java:10: UnusedAssignment: The value assigned to variable 'foo' is never used
foo = Math.min(foo, 1); // <!--- violation here
// implicit this.foo = foo;
}
}
]]></code>
</test-code>

<test-code>
<description>[java] Verify explicit canonical record constructor #4603</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Main {
public static void main(String[] args) {
System.out.println(new TestRecord(2).foo());
}
}

record TestRecord(int foo) {
TestRecord(int foo) {
foo = Math.min(foo, 1);
this.foo = foo; // explicit
}
}
]]></code>
</test-code>
</test-data>