Skip to content

Commit 8705d82

Browse files
graememorganError Prone Team
authored andcommitted
Open-source Java21 matchers.
PiperOrigin-RevId: 830636119
1 parent f101473 commit 8705d82

File tree

4 files changed

+91
-1
lines changed

4 files changed

+91
-1
lines changed

check_api/src/main/java/com/google/errorprone/bugpatterns/BugChecker.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@
5151
import com.sun.source.tree.CompilationUnitTree;
5252
import com.sun.source.tree.CompoundAssignmentTree;
5353
import com.sun.source.tree.ConditionalExpressionTree;
54+
import com.sun.source.tree.ConstantCaseLabelTree;
5455
import com.sun.source.tree.ContinueTree;
56+
import com.sun.source.tree.DeconstructionPatternTree;
57+
import com.sun.source.tree.DefaultCaseLabelTree;
5558
import com.sun.source.tree.DoWhileLoopTree;
5659
import com.sun.source.tree.EmptyStatementTree;
5760
import com.sun.source.tree.EnhancedForLoopTree;
@@ -78,6 +81,7 @@
7881
import com.sun.source.tree.PackageTree;
7982
import com.sun.source.tree.ParameterizedTypeTree;
8083
import com.sun.source.tree.ParenthesizedTree;
84+
import com.sun.source.tree.PatternCaseLabelTree;
8185
import com.sun.source.tree.PrimitiveTypeTree;
8286
import com.sun.source.tree.ProvidesTree;
8387
import com.sun.source.tree.RequiresTree;
@@ -385,10 +389,22 @@ public interface ConditionalExpressionTreeMatcher extends Suppressible {
385389
Description matchConditionalExpression(ConditionalExpressionTree tree, VisitorState state);
386390
}
387391

392+
public interface ConstantCaseLabelTreeMatcher extends Suppressible {
393+
Description matchConstantCaseLabel(ConstantCaseLabelTree tree, VisitorState state);
394+
}
395+
388396
public interface ContinueTreeMatcher extends Suppressible {
389397
Description matchContinue(ContinueTree tree, VisitorState state);
390398
}
391399

400+
public interface DeconstructionPatternTreeMatcher extends Suppressible {
401+
Description matchDeconstructionPattern(DeconstructionPatternTree tree, VisitorState state);
402+
}
403+
404+
public interface DefaultCaseLabelTreeMatcher extends Suppressible {
405+
Description matchDefaultCaseLabel(DefaultCaseLabelTree tree, VisitorState state);
406+
}
407+
392408
public interface DoWhileLoopTreeMatcher extends Suppressible {
393409
Description matchDoWhileLoop(DoWhileLoopTree tree, VisitorState state);
394410
}
@@ -498,6 +514,10 @@ public interface ParenthesizedTreeMatcher extends Suppressible {
498514
Description matchParenthesized(ParenthesizedTree tree, VisitorState state);
499515
}
500516

517+
public interface PatternCaseLabelTreeMatcher extends Suppressible {
518+
Description matchPatternCaseLabel(PatternCaseLabelTree tree, VisitorState state);
519+
}
520+
501521
public interface PrimitiveTypeTreeMatcher extends Suppressible {
502522
Description matchPrimitiveType(PrimitiveTypeTree tree, VisitorState state);
503523
}

core/src/main/java/com/google/errorprone/bugpatterns/argumentselectiondefects/ArgumentSelectionDefectChecker.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
import com.google.errorprone.BugPattern;
2323
import com.google.errorprone.VisitorState;
2424
import com.google.errorprone.bugpatterns.BugChecker;
25+
import com.google.errorprone.bugpatterns.BugChecker.DeconstructionPatternTreeMatcher;
2526
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
2627
import com.google.errorprone.bugpatterns.BugChecker.NewClassTreeMatcher;
2728
import com.google.errorprone.matchers.Description;
2829
import com.google.errorprone.names.NamingConventions;
2930
import com.google.errorprone.names.NeedlemanWunschEditDistance;
3031
import com.google.errorprone.util.ASTHelpers;
32+
import com.sun.source.tree.DeconstructionPatternTree;
3133
import com.sun.source.tree.MethodInvocationTree;
3234
import com.sun.source.tree.NewClassTree;
3335
import com.sun.tools.javac.code.Symbol.MethodSymbol;
@@ -54,7 +56,7 @@
5456
summary = "Arguments are in the wrong order or could be commented for clarity.",
5557
severity = WARNING)
5658
public class ArgumentSelectionDefectChecker extends BugChecker
57-
implements MethodInvocationTreeMatcher, NewClassTreeMatcher {
59+
implements DeconstructionPatternTreeMatcher, MethodInvocationTreeMatcher, NewClassTreeMatcher {
5860

5961
private final ArgumentChangeFinder argumentChangeFinder;
6062

@@ -99,6 +101,13 @@ public Description matchNewClass(NewClassTree tree, VisitorState state) {
99101
return visit(InvocationInfo.createFromNewClass(tree, symbol, state));
100102
}
101103

104+
@Override
105+
public Description matchDeconstructionPattern(
106+
DeconstructionPatternTree tree, VisitorState state) {
107+
var deconstructor = InvocationInfo.createFromDeconstructionPattern(tree, state);
108+
return deconstructor == null ? Description.NO_MATCH : visit(deconstructor);
109+
}
110+
102111
private Description visit(InvocationInfo invocationInfo) {
103112
Changes changes = argumentChangeFinder.findChanges(invocationInfo);
104113

core/src/main/java/com/google/errorprone/bugpatterns/argumentselectiondefects/InvocationInfo.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,22 @@
1616

1717
package com.google.errorprone.bugpatterns.argumentselectiondefects;
1818

19+
import static com.google.errorprone.util.ASTHelpers.canonicalConstructor;
20+
import static com.google.errorprone.util.ASTHelpers.getSymbol;
21+
1922
import com.google.auto.value.AutoValue;
2023
import com.google.common.collect.ImmutableList;
2124
import com.google.errorprone.VisitorState;
25+
import com.sun.source.tree.BindingPatternTree;
26+
import com.sun.source.tree.DeconstructionPatternTree;
2227
import com.sun.source.tree.MethodInvocationTree;
2328
import com.sun.source.tree.NewClassTree;
2429
import com.sun.source.tree.Tree;
30+
import com.sun.tools.javac.code.Symbol.ClassSymbol;
2531
import com.sun.tools.javac.code.Symbol.MethodSymbol;
2632
import com.sun.tools.javac.code.Symbol.VarSymbol;
2733
import java.util.List;
34+
import org.jspecify.annotations.Nullable;
2835

2936
/**
3037
* Holds information about the method invocation (or new class construction) that we are processing.
@@ -64,6 +71,26 @@ static InvocationInfo createFromNewClass(
6471
state);
6572
}
6673

74+
static @Nullable InvocationInfo createFromDeconstructionPattern(
75+
DeconstructionPatternTree tree, VisitorState state) {
76+
var symbol = getSymbol(tree.getDeconstructor());
77+
if (!(symbol instanceof ClassSymbol cs)) {
78+
return null;
79+
}
80+
81+
var constructor = canonicalConstructor(cs, state);
82+
ImmutableList.Builder<Tree> actuals = ImmutableList.builder();
83+
ImmutableList.Builder<VarSymbol> formals = ImmutableList.builder();
84+
for (int i = 0; i < constructor.getParameters().size(); ++i) {
85+
// Skip over anything that isn't binding. There might be nested patterns here, or "_"s.
86+
if (tree.getNestedPatterns().get(i) instanceof BindingPatternTree) {
87+
actuals.add(((BindingPatternTree) tree.getNestedPatterns().get(i)).getVariable());
88+
formals.add(constructor.getParameters().get(i));
89+
}
90+
}
91+
return new AutoValue_InvocationInfo(tree, constructor, actuals.build(), formals.build(), state);
92+
}
93+
6794
private static ImmutableList<VarSymbol> getFormalParametersWithoutVarArgs(
6895
MethodSymbol invokedMethodSymbol) {
6996
List<VarSymbol> formalParameters = invokedMethodSymbol.getParameters();

core/src/test/java/com/google/errorprone/bugpatterns/argumentselectiondefects/ArgumentSelectionDefectCheckerTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,40 @@ record Foo(String first, String second) {}
400400
.doTest();
401401
}
402402

403+
@Test
404+
public void recordDeconstruction() {
405+
testHelper
406+
.addSourceLines(
407+
"Test.java",
408+
"""
409+
class Test {
410+
void test(Foo foo) {
411+
switch (foo) {
412+
// BUG: Diagnostic contains: may have been swapped
413+
case Foo(String second, String first, _) -> {}
414+
default -> {}
415+
}
416+
}
417+
418+
void test2(Foo foo) {
419+
switch (foo) {
420+
// BUG: Diagnostic contains: may have been swapped
421+
case Foo(_, _, Foo(String second, String first, _)) -> {}
422+
default -> {}
423+
}
424+
}
425+
}
426+
427+
record Foo(String first, String second, Foo foo) {}
428+
""")
429+
.setArgs(
430+
"-parameters",
431+
"--enable-preview",
432+
"--release",
433+
Integer.toString(Runtime.version().feature()))
434+
.doTest();
435+
}
436+
403437
public record Foo(String first, String second) {}
404438

405439
@Test

0 commit comments

Comments
 (0)