Skip to content

Commit ab45284

Browse files
cushonError Prone Team
authored andcommitted
Keep some mandatory parens in PatternMatchingInstanceOf
Fixes #4923 PiperOrigin-RevId: 739213124
1 parent 0eede30 commit ab45284

File tree

2 files changed

+90
-4
lines changed

2 files changed

+90
-4
lines changed

core/src/main/java/com/google/errorprone/bugpatterns/PatternMatchingInstanceof.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,7 @@ public Void visitTypeCast(TypeCastTree node, Void unused) {
244244
if (getSymbol(node.getExpression()) instanceof VarSymbol v) {
245245
if (v.equals(symbol)
246246
&& state.getTypes().isSubtype(targetType, getType(node.getType()))) {
247-
usages.add(
248-
getCurrentPath().getParentPath().getLeaf() instanceof ParenthesizedTree
249-
? getCurrentPath().getParentPath()
250-
: getCurrentPath());
247+
usages.add(getUsage(getCurrentPath()));
251248
}
252249
}
253250
return super.visitTypeCast(node, null);
@@ -259,6 +256,29 @@ public Void visitTypeCast(TypeCastTree node, Void unused) {
259256
return usages.build();
260257
}
261258

259+
private static TreePath getUsage(TreePath currentPath) {
260+
TreePath parentPath = currentPath.getParentPath();
261+
return parentPath.getLeaf() instanceof ParenthesizedTree && !requiresParentheses(parentPath)
262+
? parentPath
263+
: currentPath;
264+
}
265+
266+
private static boolean requiresParentheses(TreePath path) {
267+
// This isn't ASTHelpers.requiresParentheses, because we want to know if parens are needed when
268+
// replacing a cast with the cast's expression, i.e. `((Foo) bar)` -> `(bar)`
269+
return switch (path.getParentPath().getLeaf().getKind()) {
270+
case IDENTIFIER,
271+
MEMBER_SELECT,
272+
METHOD_INVOCATION,
273+
ARRAY_ACCESS,
274+
PARENTHESIZED,
275+
NEW_CLASS,
276+
MEMBER_REFERENCE ->
277+
false;
278+
default -> true;
279+
};
280+
}
281+
262282
private static boolean isReassigned(VarSymbol symbol, Iterable<Tree> trees) {
263283
AtomicBoolean isReassigned = new AtomicBoolean(false);
264284
new TreeScanner<Void, Void>() {

core/src/test/java/com/google/errorprone/bugpatterns/PatternMatchingInstanceofTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,4 +764,70 @@ int f(Object o) {
764764
.expectUnchanged()
765765
.doTest();
766766
}
767+
768+
// https://github.com/google/error-prone/issues/4923
769+
@Test
770+
public void requiredParentheses_retainedInFix() {
771+
assume().that(Runtime.version().feature()).isAtLeast(21);
772+
helper
773+
.addInputLines(
774+
"Test1.java",
775+
"""
776+
public class Test1 {
777+
778+
int test_switch() {
779+
Object o = 1;
780+
if (o instanceof Integer) {
781+
// Next line will be turned into "return switch i {".
782+
return switch ((Integer) o) {
783+
case 0 -> 0;
784+
default -> 1;
785+
};
786+
}
787+
return 0;
788+
}
789+
790+
boolean test_if() {
791+
Object o = false;
792+
if (o instanceof Boolean) {
793+
// Next line will be turned into "if b {".
794+
if ((Boolean) o) {
795+
return (Boolean) o;
796+
}
797+
}
798+
return false;
799+
}
800+
}
801+
""")
802+
.addOutputLines(
803+
"Test1.java",
804+
"""
805+
public class Test1 {
806+
807+
int test_switch() {
808+
Object o = 1;
809+
if (o instanceof Integer i) {
810+
// Next line will be turned into "return switch i {".
811+
return switch (i) {
812+
case 0 -> 0;
813+
default -> 1;
814+
};
815+
}
816+
return 0;
817+
}
818+
819+
boolean test_if() {
820+
Object o = false;
821+
if (o instanceof Boolean b) {
822+
// Next line will be turned into "if b {".
823+
if (b) {
824+
return b;
825+
}
826+
}
827+
return false;
828+
}
829+
}
830+
""")
831+
.doTest(BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH);
832+
}
767833
}

0 commit comments

Comments
 (0)