Skip to content

Commit

Permalink
Merge pull request #6635 from lahodaj/javavscode-53
Browse files Browse the repository at this point in the history
Assignments to parameters to record compact constructors should not be marked as unused.
  • Loading branch information
neilcsmith-net authored Oct 31, 2023
2 parents 8dd9867 + 6468b24 commit 68bb0e8
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Set;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.netbeans.api.java.source.CompilationInfo;
Expand Down Expand Up @@ -133,25 +134,44 @@ private static Pair<Set<Tree>, Set<Element>> computeUsedAssignments(final HintCo
@TriggerPattern("$mods$ $type $var = $value;")
})
public static ErrorDescription unusedAssignment(final HintContext ctx) {
final CompilationInfo info = ctx.getInfo();
Element var = info.getTrees().getElement(ctx.getVariables().get("$var"));

if (var == null || !LOCAL_VARIABLES.contains(var.getKind()) ||
isImplicitParamOfRecordCanonicalConstructor(info, var)) {
return null;
}

final String unusedAssignmentLabel = NbBundle.getMessage(UnusedAssignmentOrBranch.class, "LBL_UNUSED_ASSIGNMENT_LABEL");
Pair<Set<Tree>, Set<Element>> computedAssignments = computeUsedAssignments(ctx);

if (ctx.isCanceled() || computedAssignments == null) return null;

final CompilationInfo info = ctx.getInfo();
final Set<Tree> usedAssignments = computedAssignments.first();
final Set<Element> usedVariables = computedAssignments.second();
Element var = info.getTrees().getElement(ctx.getVariables().get("$var"));
TreePath valuePath = ctx.getVariables().get("$value");
Tree value = (valuePath == null ? ctx.getPath() : valuePath).getLeaf();

if (var != null && LOCAL_VARIABLES.contains(var.getKind()) && !usedAssignments.contains(value) && usedVariables.contains(var)) {
if (!usedAssignments.contains(value) && usedVariables.contains(var)) {
return ErrorDescriptionFactory.forTree(ctx, value, unusedAssignmentLabel);
}

return null;
}


private static boolean isImplicitParamOfRecordCanonicalConstructor(CompilationInfo info, Element el) {
Element enclosingElement = el.getEnclosingElement();

if (enclosingElement.getKind() != ElementKind.CONSTRUCTOR) {
return false;
}

ExecutableElement constr = (ExecutableElement) enclosingElement;

return info.getElements().isCompactConstructor(constr) &&
constr.getParameters().contains(el);
}

private static boolean mayHaveSideEffects(HintContext ctx, TreePath path) {
SideEffectVisitor visitor = new SideEffectVisitor(ctx).stopOnUnknownMethods(true);
Tree culprit = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.netbeans.modules.java.hints.bugs;

import org.junit.Assume;
import org.netbeans.junit.NbTestCase;
import org.netbeans.modules.java.hints.test.api.HintTest;

Expand Down Expand Up @@ -211,4 +212,30 @@ public void testImplicitlyStaticFieldWithInitializer() throws Exception {
.run(UnusedAssignmentOrBranch.class)
.assertWarnings();
}

public void testRecordCompactConstructor() throws Exception {
Assume.assumeTrue(isRecordClassPresent());

HintTest
.create()
.input("package test;\n" +
"\n" +
"public record Test(int i, int j) {\n" +
" public Test {\n" +
" i = -i;\n" +
" }\n" +
"}")
.sourceLevel("21")
.run(UnusedAssignmentOrBranch.class)
.assertWarnings();
}

private boolean isRecordClassPresent() {
try {
Class.forName("java.lang.Record");
return true;
} catch (ClassNotFoundException ex) {
return false;
}
}
}

0 comments on commit 68bb0e8

Please sign in to comment.