Skip to content

Commit b822dd4

Browse files
graememorganError Prone Team
authored andcommitted
ImmutableChecker: handle local classes.
I feel increasingly guilty at the way this is diverging from ThreadSafety; I think there's a refactor to be had there. PiperOrigin-RevId: 450386803
1 parent 98dfcaf commit b822dd4

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableChecker.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static com.google.errorprone.util.ASTHelpers.getSymbol;
2626
import static com.google.errorprone.util.ASTHelpers.getType;
2727
import static com.google.errorprone.util.ASTHelpers.hasAnnotation;
28+
import static com.google.errorprone.util.ASTHelpers.isLocal;
2829
import static com.google.errorprone.util.ASTHelpers.isSameType;
2930
import static com.google.errorprone.util.ASTHelpers.isSubtype;
3031
import static com.google.errorprone.util.ASTHelpers.targetType;
@@ -321,6 +322,11 @@ public Description matchClass(ClassTree tree, VisitorState state) {
321322
(Tree matched, Violation violation) ->
322323
describeClass(matched, sym, annotation, violation));
323324

325+
Type superType = immutableSupertype(sym, state);
326+
if (handleAnonymousClasses && superType != null && isLocal(sym)) {
327+
checkClosedTypes(tree, state, superType.tsym, analysis);
328+
}
329+
324330
if (!info.isPresent()) {
325331
return NO_MATCH;
326332
}

core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableCheckerTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,52 @@ public void extendsImmutableAnnotated_mutableBounds() {
374374
.doTest();
375375
}
376376

377+
@Test
378+
public void withinMutableClass() {
379+
compilationHelper
380+
.addSourceLines(
381+
"A.java",
382+
"import com.google.errorprone.annotations.Immutable;",
383+
"import java.util.ArrayList;",
384+
"import java.util.List;",
385+
"class A {",
386+
" List<Integer> xs = new ArrayList<>();",
387+
" // BUG: Diagnostic contains: has mutable enclosing instance",
388+
" @Immutable class B {",
389+
" int get() {",
390+
" return xs.get(0);",
391+
" }",
392+
" }",
393+
"}")
394+
.doTest();
395+
}
396+
397+
@Test
398+
public void localClassCapturingMutableState() {
399+
compilationHelper
400+
.addSourceLines(
401+
"A.java",
402+
"import com.google.errorprone.annotations.Immutable;",
403+
"import java.util.ArrayList;",
404+
"import java.util.List;",
405+
"@Immutable",
406+
"class A {",
407+
" @Immutable interface B { int get(); }",
408+
" void test() {",
409+
" List<Integer> xs = new ArrayList<>();",
410+
" @Immutable",
411+
" // BUG: Diagnostic contains: but 'List' is mutable",
412+
" class C implements B {",
413+
" @Override",
414+
" public int get() {",
415+
" return xs.get(0);",
416+
" }",
417+
" }",
418+
" }",
419+
"}")
420+
.doTest();
421+
}
422+
377423
@Test
378424
public void typeParameterWithImmutableBound() {
379425
compilationHelper

0 commit comments

Comments
 (0)