Skip to content

Commit 7926dbc

Browse files
graememorganError Prone Team
authored andcommitted
Fix MustBeClosedChecker crash on flexible constructors.
Fixes external #5529 PiperOrigin-RevId: 875182882
1 parent d08f003 commit 7926dbc

2 files changed

Lines changed: 62 additions & 10 deletions

File tree

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@
3838
import com.google.errorprone.util.ASTHelpers;
3939
import com.sun.source.tree.ClassTree;
4040
import com.sun.source.tree.ExpressionStatementTree;
41+
import com.sun.source.tree.IdentifierTree;
4142
import com.sun.source.tree.MethodInvocationTree;
4243
import com.sun.source.tree.MethodTree;
4344
import com.sun.source.tree.StatementTree;
4445
import com.sun.source.tree.Tree;
4546
import com.sun.tools.javac.code.Symbol.MethodSymbol;
46-
import java.util.List;
4747

4848
/**
4949
* Checks if a constructor or method annotated with {@link
@@ -159,15 +159,19 @@ public Description matchClass(ClassTree tree, VisitorState state) {
159159
}
160160

161161
private static boolean invokedConstructorMustBeClosed(VisitorState state, MethodTree methodTree) {
162-
// The first statement in a constructor should be an invocation of the super/this constructor.
163-
List<? extends StatementTree> statements = methodTree.getBody().getStatements();
164-
if (statements.isEmpty()) {
165-
// Not sure how the body would be empty, but just filter it out in case.
166-
return false;
162+
for (StatementTree statement : methodTree.getBody().getStatements()) {
163+
if (!(statement instanceof ExpressionStatementTree est)) {
164+
continue;
165+
}
166+
if (!(est.getExpression() instanceof MethodInvocationTree mit)) {
167+
continue;
168+
}
169+
if (mit.getMethodSelect() instanceof IdentifierTree id
170+
&& (id.getName().contentEquals("super") || id.getName().contentEquals("this"))) {
171+
MethodSymbol invokedConstructorSymbol = ASTHelpers.getSymbol(mit);
172+
return hasAnnotation(invokedConstructorSymbol, MUST_BE_CLOSED_ANNOTATION, state);
173+
}
167174
}
168-
ExpressionStatementTree est = (ExpressionStatementTree) statements.getFirst();
169-
MethodInvocationTree mit = (MethodInvocationTree) est.getExpression();
170-
MethodSymbol invokedConstructorSymbol = ASTHelpers.getSymbol(mit);
171-
return hasAnnotation(invokedConstructorSymbol, MUST_BE_CLOSED_ANNOTATION, state);
175+
return false;
172176
}
173177
}

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package com.google.errorprone.bugpatterns;
1818

19+
import static com.google.common.truth.TruthJUnit.assume;
20+
1921
import com.google.errorprone.BugCheckerRefactoringTestHelper;
2022
import com.google.errorprone.CompilationTestHelper;
2123
import org.junit.Ignore;
@@ -940,6 +942,52 @@ void forLoopUpdate() {
940942
.doTest();
941943
}
942944

945+
@Test
946+
public void flexibleConstructor() {
947+
assume().that(Runtime.version().feature()).isAtLeast(22);
948+
949+
compilationHelper
950+
.addSourceLines(
951+
"Test.java",
952+
"""
953+
import com.google.errorprone.annotations.MustBeClosed;
954+
955+
class Test {
956+
static class Parent implements AutoCloseable {
957+
@MustBeClosed
958+
Parent() {}
959+
960+
@Override
961+
public void close() {}
962+
}
963+
964+
static class Child extends Parent {
965+
// BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed
966+
Child(int i) {
967+
i++;
968+
super();
969+
}
970+
}
971+
972+
static class Other implements AutoCloseable {
973+
@MustBeClosed
974+
Other(int i) {}
975+
976+
// BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed
977+
Other() {
978+
int i = 1;
979+
this(i);
980+
}
981+
982+
@Override
983+
public void close() {}
984+
}
985+
}
986+
""")
987+
.setArgs("--enable-preview", "--release", Integer.toString(Runtime.version().feature()))
988+
.doTest();
989+
}
990+
943991
@Test
944992
public void localVariableTypeInference() {
945993
refactoringHelper

0 commit comments

Comments
 (0)