From 0e7e594ffaffbbfd67c980750ffd7d0d26586035 Mon Sep 17 00:00:00 2001 From: lukman48 Date: Thu, 11 Jun 2026 05:25:58 +0700 Subject: [PATCH] Make AssignmentExpression matcher parenthesis-invariant When an assignment is wrapped in ParenthesizedTree (e.g. int k = (a = b)), the checker previously did not look through the parentheses to determine the enclosing context, causing inconsistent behavior between int k = (a = b) and int k = a = b. Fix: unwrap ParenthesizedTree nodes before examining the parent context. The C-ism exemption ((a = getFoo()) != null) is checked before unwrapping so it still applies correctly. Fixes #5827 --- .../bugpatterns/AssignmentExpression.java | 18 ++++++++++++------ .../bugpatterns/AssignmentExpressionTest.java | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/AssignmentExpression.java b/core/src/main/java/com/google/errorprone/bugpatterns/AssignmentExpression.java index 2b945778185..ad44ed76dab 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/AssignmentExpression.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/AssignmentExpression.java @@ -33,6 +33,7 @@ import com.sun.source.tree.ParenthesizedTree; import com.sun.source.tree.Tree; import com.sun.source.tree.VariableTree; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Symbol.VarSymbol; /** A BugPattern; see the summary. */ @@ -45,7 +46,17 @@ public final class AssignmentExpression extends BugChecker implements Assignment @Override public Description matchAssignment(AssignmentTree tree, VisitorState state) { - Tree parent = state.getPath().getParentPath().getLeaf(); + TreePath parentPath = state.getPath().getParentPath(); + // Exempt the C-ism of (foo = getFoo()) != null, etc. before unwrapping parens. + if (parentPath.getLeaf() instanceof ParenthesizedTree + && parentPath.getParentPath().getLeaf() instanceof BinaryTree) { + return Description.NO_MATCH; + } + // Unwrap ParenthesizedTree for parenthesis-invariant matching. + while (parentPath.getLeaf() instanceof ParenthesizedTree) { + parentPath = parentPath.getParentPath(); + } + Tree parent = parentPath.getLeaf(); if (parent instanceof ExpressionStatementTree) { return Description.NO_MATCH; } @@ -55,11 +66,6 @@ public Description matchAssignment(AssignmentTree tree, VisitorState state) { if (parent instanceof LambdaExpressionTree) { return Description.NO_MATCH; } - // Exempt the C-ism of (foo = getFoo()) != null, etc. - if (parent instanceof ParenthesizedTree - && state.getPath().getParentPath().getParentPath().getLeaf() instanceof BinaryTree) { - return Description.NO_MATCH; - } // Detect duplicate assignments: a = a = foo() so that we can generate a fix. if (isDuplicateAssignment(tree, parent)) { return describeMatch( diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/AssignmentExpressionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/AssignmentExpressionTest.java index 37c250ac7ba..107bd44c0cb 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/AssignmentExpressionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/AssignmentExpressionTest.java @@ -147,4 +147,22 @@ Object test() { """) .doTest(); } + + @Test + public void parenthesizedAssignmentInDeclaration() { + helper + .addSourceLines( + "Test.java", + """ + class Test { + void test() { + int a = 0; + int b = 1; + // BUG: Diagnostic contains: + int k = (a = b); + } + } + """) + .doTest(); + } }