diff --git a/core/src/test/java/com/google/errorprone/ErrorProneCompilerIntegrationTest.java b/core/src/test/java/com/google/errorprone/ErrorProneCompilerIntegrationTest.java index db17f9e2a66..824104ffbc6 100644 --- a/core/src/test/java/com/google/errorprone/ErrorProneCompilerIntegrationTest.java +++ b/core/src/test/java/com/google/errorprone/ErrorProneCompilerIntegrationTest.java @@ -278,10 +278,12 @@ public void ignoreGeneratedSuperInvocations() { compiler.compile( Arrays.asList( forSourceLines( - "Test.java", // - "public class Test {", - " public Test() {}", - "}"))); + "Test.java", + """ + public class Test { + public Test() {} + } + """))); assertWithMessage("[SuperCallMatcher]") .that(diagnosticHelper.getDiagnostics()) @@ -301,10 +303,12 @@ public void invalidFlagCausesCmdErrResult() { args, Arrays.asList( forSourceLines( - "Test.java", // - "public class Test {", - " public Test() {}", - "}")))); + "Test.java", + """ + public class Test { + public Test() {} + } + """)))); } @Test @@ -494,12 +498,14 @@ public void crashSourcePosition() { Arrays.asList( forSourceLines( "test/Test.java", - "package Test;", - "class Test {", - " void f() {", - " return;", - " }", - "}"))); + """ + package Test; + class Test { + void f() { + return; + } + } + """))); assertWithMessage(outputStream.toString()).that(exitCode).isEqualTo(Result.ERROR); assertThat(diagnosticHelper.getDiagnostics()).hasSize(1); Diagnostic diag = @@ -530,9 +536,11 @@ public void compilePolicy_byfile() { new String[] {"-XDcompilePolicy=byfile"}, Arrays.asList( forSourceLines( - "Test.java", // - "package test;", - "class Test {}"))); + "Test.java", + """ + package test; + class Test {} + """))); outputStream.flush(); assertWithMessage(outputStream.toString()).that(exitCode).isEqualTo(Result.OK); } @@ -544,9 +552,11 @@ public void compilePolicy_simple() { new String[] {"-XDcompilePolicy=simple"}, Arrays.asList( forSourceLines( - "Test.java", // - "package test;", - "class Test {}"))); + "Test.java", + """ + package test; + class Test {} + """))); outputStream.flush(); assertWithMessage(outputStream.toString()).that(exitCode).isEqualTo(Result.OK); } @@ -573,10 +583,12 @@ public void compilationWithError() { Arrays.asList( forSourceLines( "Test.java", - "package test;", - "public class Test {", - " Object f() { return new NoSuch(); }", - "}"))); + """ + package test; + public class Test { + Object f() { return new NoSuch(); } + } + """))); outputStream.flush(); String output = diagnosticHelper.getDiagnostics().toString(); assertThat(output).contains("error: cannot find symbol"); @@ -616,10 +628,12 @@ public void checkerWithFlags() { Arrays.asList( forSourceLines( "Test.java", - "package test;", - "public class Test {", - " Object f() { return \"XYLOPHONE\"; }", - "}")); + """ + package test; + public class Test { + Object f() { return "XYLOPHONE"; } + } + """)); compilerBuilder.report(ScannerSupplier.fromBugCheckerClasses(ForbiddenString.class)); compiler = compilerBuilder.build(); @@ -636,10 +650,12 @@ public void flagsAreResetOnNextCompilation() { Arrays.asList( forSourceLines( "Test.java", - "package test;", - "public class Test {", - " Object f() { return \"BANANAS\"; }", - "}")); + """ + package test; + public class Test { + Object f() { return "BANANAS"; } + } + """)); // First compile forbids "bananas", should fail. compilerBuilder.report(ScannerSupplier.fromBugCheckerClasses(ForbiddenString.class)); diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/AnnotationPositionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/AnnotationPositionTest.java index 24793557753..a9d6637b752 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/AnnotationPositionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/AnnotationPositionTest.java @@ -37,21 +37,25 @@ public final class AnnotationPositionTest { BugCheckerRefactoringTestHelper.newInstance(AnnotationPosition.class, getClass()) .addInputLines( "TypeUse.java", - "import java.lang.annotation.ElementType;", - "import java.lang.annotation.Target;", - "@Target({ElementType.TYPE_USE})", - "@interface TypeUse {", - " String value() default \"\";", - "}") + """ + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + @Target({ElementType.TYPE_USE}) + @interface TypeUse { + String value() default ""; + } + """) .expectUnchanged() .addInputLines( "EitherUse.java", - "import java.lang.annotation.ElementType;", - "import java.lang.annotation.Target;", - "@Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.TYPE})", - "@interface EitherUse {", - " String value() default \"\";", - "}") + """ + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + @Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.TYPE}) + @interface EitherUse { + String value() default ""; + } + """) .expectUnchanged() .addInputLines( "NonTypeUse.java", // @@ -62,37 +66,45 @@ public final class AnnotationPositionTest { CompilationTestHelper.newInstance(AnnotationPosition.class, getClass()) .addSourceLines( "TypeUse.java", - "import java.lang.annotation.ElementType;", - "import java.lang.annotation.Target;", - "@Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.TYPE})", - "@interface TypeUse {", - " String value() default \"\";", - "}") + """ + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + @Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.TYPE}) + @interface TypeUse { + String value() default ""; + } + """) .addSourceLines( "NonTypeUse.java", // "@interface NonTypeUse {}") .addSourceLines( "EitherUse.java", - "import java.lang.annotation.ElementType;", - "import java.lang.annotation.Target;", - "@Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.TYPE})", - "@interface EitherUse {", - " String value() default \"\";", - "}"); + """ + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + @Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.TYPE}) + @interface EitherUse { + String value() default ""; + } + """); @Test public void nonTypeAnnotation() { refactoringHelper .addInputLines( - "Test.java", // - "interface Test {", // - " public @Override boolean equals(Object o);", - "}") + "Test.java", + """ + interface Test { + public @Override boolean equals(Object o); + } + """) .addOutputLines( - "Test.java", // - "interface Test {", - " @Override public boolean equals(Object o);", - "}") + "Test.java", + """ + interface Test { + @Override public boolean equals(Object o); + } + """) .doTest(TEXT_MATCH); } @@ -101,18 +113,22 @@ public void interspersedJavadoc() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " @NonTypeUse", - " /** Javadoc! */", - " public void foo();", - "}") + """ + interface Test { + @NonTypeUse + /** Javadoc! */ + public void foo(); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /** Javadoc! */", - " @NonTypeUse", - " public void foo();", - "}") + """ + interface Test { + /** Javadoc! */ + @NonTypeUse + public void foo(); + } + """) .doTest(TEXT_MATCH); } @@ -121,12 +137,14 @@ public void interspersedJavadoc_treeAlreadyHasJavadoc_noSuggestion() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " /** Actually Javadoc. */", - " @NonTypeUse", - " /** Javadoc! */", - " public void foo();", - "}") + """ + interface Test { + /** Actually Javadoc. */ + @NonTypeUse + /** Javadoc! */ + public void foo(); + } + """) .expectUnchanged() .doTest(TEXT_MATCH); } @@ -136,20 +154,24 @@ public void interspersedJavadoc_withComment() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " @NonTypeUse", - " /** Javadoc! */", - " // TODO: fix", - " public void foo();", - "}") + """ + interface Test { + @NonTypeUse + /** Javadoc! */ + // TODO: fix + public void foo(); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /** Javadoc! */", - " @NonTypeUse", - " // TODO: fix", - " public void foo();", - "}") + """ + interface Test { + /** Javadoc! */ + @NonTypeUse + // TODO: fix + public void foo(); + } + """) .doTest(TEXT_MATCH); } @@ -158,18 +180,20 @@ public void negatives() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " /** Javadoc */", - " @NonTypeUse", - " public boolean foo();", - " @NonTypeUse", - " public boolean bar();", - " public @EitherUse boolean baz();", - " /** Javadoc */", - " @NonTypeUse", - " // comment", - " public boolean quux();", - "}") + """ + interface Test { + /** Javadoc */ + @NonTypeUse + public boolean foo(); + @NonTypeUse + public boolean bar(); + public @EitherUse boolean baz(); + /** Javadoc */ + @NonTypeUse + // comment + public boolean quux(); + } + """) .expectUnchanged() .doTest(TEXT_MATCH); } @@ -179,14 +203,18 @@ public void negative_parameter() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " public boolean foo(final @NonTypeUse String s);", - "}") + """ + interface Test { + public boolean foo(final @NonTypeUse String s); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " public boolean foo(@NonTypeUse final String s);", - "}") + """ + interface Test { + public boolean foo(@NonTypeUse final String s); + } + """) .doTest(TEXT_MATCH); } @@ -195,25 +223,29 @@ public void typeAnnotation() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " /** Javadoc */", - " public @NonTypeUse @EitherUse String foo();", - " /** Javadoc */", - " public @EitherUse @NonTypeUse String bar();", - " public @EitherUse /** Javadoc */ @NonTypeUse String baz();", - " public @EitherUse static @NonTypeUse int quux() { return 1; }", - "}") + """ + interface Test { + /** Javadoc */ + public @NonTypeUse @EitherUse String foo(); + /** Javadoc */ + public @EitherUse @NonTypeUse String bar(); + public @EitherUse /** Javadoc */ @NonTypeUse String baz(); + public @EitherUse static @NonTypeUse int quux() { return 1; } + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /** Javadoc */", - " @NonTypeUse public @EitherUse String foo();", - " /** Javadoc */", - " @NonTypeUse public @EitherUse String bar();", - " /** Javadoc */", - " @NonTypeUse public @EitherUse String baz();", - " @NonTypeUse public static @EitherUse int quux() { return 1; }", - "}") + """ + interface Test { + /** Javadoc */ + @NonTypeUse public @EitherUse String foo(); + /** Javadoc */ + @NonTypeUse public @EitherUse String bar(); + /** Javadoc */ + @NonTypeUse public @EitherUse String baz(); + @NonTypeUse public static @EitherUse int quux() { return 1; } + } + """) .doTest(TEXT_MATCH); } @@ -222,15 +254,19 @@ public void variables() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " public @EitherUse static /** Javadoc */ @NonTypeUse int foo = 1;", - "}") + """ + interface Test { + public @EitherUse static /** Javadoc */ @NonTypeUse int foo = 1; + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /** Javadoc */", - " @NonTypeUse public static @EitherUse int foo = 1;", - "}") + """ + interface Test { + /** Javadoc */ + @NonTypeUse public static @EitherUse int foo = 1; + } + """) .doTest(TEXT_MATCH); } @@ -238,13 +274,17 @@ public void variables() { public void classes() { refactoringHelper .addInputLines( - "Test.java", // - "public @NonTypeUse", - "interface Test {}") + "Test.java", + """ + public @NonTypeUse + interface Test {} + """) .addOutputLines( - "Test.java", // - "@NonTypeUse", - "public interface Test {}") + "Test.java", + """ + @NonTypeUse + public interface Test {} + """) .doTest(TEXT_MATCH); } @@ -255,9 +295,11 @@ public void class_typeUseBeforeModifiers() { "Test.java", // "public @EitherUse interface Test {}") .addOutputLines( - "Test.java", // - "@EitherUse", - "public interface Test {}") + "Test.java", + """ + @EitherUse + public interface Test {} + """) .doTest(TEXT_MATCH); } @@ -268,9 +310,11 @@ public void class_intermingledJavadoc() { "Test.java", // "@NonTypeUse public /** Javadoc */ final class Test {}") .addOutputLines( - "Test.java", // - "/** Javadoc */", - "@NonTypeUse public final class Test {}") + "Test.java", + """ + /** Javadoc */ + @NonTypeUse public final class Test {} + """) .doTest(TEXT_MATCH); } @@ -279,16 +323,20 @@ public void betweenModifiers() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " public @EitherUse static @NonTypeUse int foo() { return 1; }", - " public @EitherUse @NonTypeUse static int bar() { return 1; }", - "}") + """ + interface Test { + public @EitherUse static @NonTypeUse int foo() { return 1; } + public @EitherUse @NonTypeUse static int bar() { return 1; } + } + """) .addOutputLines( "Test.java", - "interface Test {", - " @NonTypeUse public static @EitherUse int foo() { return 1; }", - " @NonTypeUse public static @EitherUse int bar() { return 1; }", - "}") + """ + interface Test { + @NonTypeUse public static @EitherUse int foo() { return 1; } + @NonTypeUse public static @EitherUse int bar() { return 1; } + } + """) .doTest(TEXT_MATCH); } @@ -297,14 +345,18 @@ public void betweenModifiersWithValue() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " public final @EitherUse(\"foo\") int foo(final int a) { return 1; }", - "}") + """ + class Test { + public final @EitherUse("foo") int foo(final int a) { return 1; } + } + """) .addOutputLines( "Test.java", - "class Test {", - " public final @EitherUse(\"foo\") int foo(final int a) { return 1; }", - "}") + """ + class Test { + public final @EitherUse("foo") int foo(final int a) { return 1; } + } + """) .doTest(TEXT_MATCH); } @@ -313,19 +365,21 @@ public void interspersedComments() { refactoringHelper .addInputLines( "Test.java", - "interface Test {", - " public @EitherUse /** Javadoc */ @NonTypeUse String baz();", - " /* a */ public /* b */ @EitherUse /* c */ static /* d */ " - + "@NonTypeUse /* e */ int quux() { return 1; }", - "}") + """ +interface Test { + public @EitherUse /** Javadoc */ @NonTypeUse String baz(); + /* a */ public /* b */ @EitherUse /* c */ static /* d */ @NonTypeUse /* e */ int quux() { return 1; } +} +""") .addOutputLines( "Test.java", - "interface Test {", - " /** Javadoc */", - " @NonTypeUse public @EitherUse String baz();", - " /* a */ @NonTypeUse public /* b */ /* c */ static @EitherUse " - + "/* d */ /* e */ int quux() { return 1; }", - "}") + """ +interface Test { + /** Javadoc */ + @NonTypeUse public @EitherUse String baz(); + /* a */ @NonTypeUse public /* b */ /* c */ static @EitherUse /* d */ /* e */ int quux() { return 1; } +} +""") .doTest(TEXT_MATCH); } @@ -334,14 +388,16 @@ public void messages() { helper .addSourceLines( "Test.java", - "interface Test {", - " // BUG: Diagnostic contains: @Override is not a TYPE_USE annotation", - " public @Override boolean equals(Object o);", - " // BUG: Diagnostic contains: @Override, @NonTypeUse are not TYPE_USE annotations", - " public @Override @NonTypeUse int hashCode();", - " // BUG: Diagnostic contains: Javadocs should appear before any modifiers", - " @NonTypeUse /** Javadoc */ public boolean bar();", - "}") + """ + interface Test { + // BUG: Diagnostic contains: @Override is not a TYPE_USE annotation + public @Override boolean equals(Object o); + // BUG: Diagnostic contains: @Override, @NonTypeUse are not TYPE_USE annotations + public @Override @NonTypeUse int hashCode(); + // BUG: Diagnostic contains: Javadocs should appear before any modifiers + @NonTypeUse /** Javadoc */ public boolean bar(); + } + """) .doTest(); } @@ -349,11 +405,13 @@ public void messages() { public void diagnostic() { helper .addSourceLines( - "Test.java", // - "interface Test {", - " // BUG: Diagnostic contains: is a TYPE_USE", - " public @EitherUse static int foo = 1;", - "}") + "Test.java", + """ + interface Test { + // BUG: Diagnostic contains: is a TYPE_USE + public @EitherUse static int foo = 1; + } + """) .doTest(); } @@ -363,17 +421,21 @@ public void sealedInterface() { assume().that(Runtime.version().feature()).isAtLeast(15); refactoringHelper .addInputLines( - "Test.java", // - "/** Javadoc! */", - "sealed @Deprecated interface Test {", - " final class A implements Test {}", - "}") + "Test.java", + """ + /** Javadoc! */ + sealed @Deprecated interface Test { + final class A implements Test {} + } + """) .addOutputLines( - "Test.java", // - "/** Javadoc! */", - "sealed @Deprecated interface Test {", - " final class A implements Test {}", - "}") + "Test.java", + """ + /** Javadoc! */ + sealed @Deprecated interface Test { + final class A implements Test {} + } + """) .setArgs("--enable-preview", "--release", Integer.toString(Runtime.version().feature())) .doTest(TEXT_MATCH); } @@ -382,15 +444,19 @@ public void sealedInterface() { public void typeArgument_annotationOfEitherUse_canRemainBefore() { refactoringHelper .addInputLines( - "Test.java", // - "interface T {", - " @EitherUse T f();", - "}") + "Test.java", + """ + interface T { + @EitherUse T f(); + } + """) .addOutputLines( - "Test.java", // - "interface T {", - " @EitherUse T f();", - "}") + "Test.java", + """ + interface T { + @EitherUse T f(); + } + """) .doTest(TEXT_MATCH); } @@ -398,15 +464,19 @@ public void typeArgument_annotationOfEitherUse_canRemainBefore() { public void typeArgument_typeUseAnnotation_movesAfter() { refactoringHelper .addInputLines( - "Test.java", // - "interface T {", - " @TypeUse T f();", - "}") + "Test.java", + """ + interface T { + @TypeUse T f(); + } + """) .addOutputLines( - "Test.java", // - "interface T {", - " @TypeUse T f();", - "}") + "Test.java", + """ + interface T { + @TypeUse T f(); + } + """) .doTest(TEXT_MATCH); } @@ -414,17 +484,21 @@ public void typeArgument_typeUseAnnotation_movesAfter() { public void genericsWithBounds() { refactoringHelper .addInputLines( - "Test.java", // - "import java.util.List;", - "interface T {", - " @TypeUse > T f();", - "}") + "Test.java", + """ + import java.util.List; + interface T { + @TypeUse > T f(); + } + """) .addOutputLines( - "Test.java", // - "import java.util.List;", - "interface T {", - " > @TypeUse T f();", - "}") + "Test.java", + """ + import java.util.List; + interface T { + > @TypeUse T f(); + } + """) .doTest(TEXT_MATCH); } @@ -432,15 +506,19 @@ public void genericsWithBounds() { public void typeUseAndNonTypeUse_inWrongOrder() { refactoringHelper .addInputLines( - "Test.java", // - "interface T {", - " @TypeUse @NonTypeUse T f();", - "}") + "Test.java", + """ + interface T { + @TypeUse @NonTypeUse T f(); + } + """) .addOutputLines( - "Test.java", // - "interface T {", - " @NonTypeUse @TypeUse T f();", - "}") + "Test.java", + """ + interface T { + @NonTypeUse @TypeUse T f(); + } + """) .doTest(TEXT_MATCH); } @@ -448,11 +526,13 @@ public void typeUseAndNonTypeUse_inWrongOrder() { public void annotationOfEitherUse_isAllowedToRemainBeforeModifiers() { refactoringHelper .addInputLines( - "Test.java", // - "interface T {", - " @NonTypeUse @EitherUse public T a();", - " @NonTypeUse public @EitherUse T b();", - "}") + "Test.java", + """ + interface T { + @NonTypeUse @EitherUse public T a(); + @NonTypeUse public @EitherUse T b(); + } + """) .expectUnchanged() .doTest(TEXT_MATCH); } @@ -461,14 +541,16 @@ public void annotationOfEitherUse_isAllowedToRemainBeforeModifiers() { public void constructor() { refactoringHelper .addInputLines( - "Test.java", // - "import javax.inject.Inject;", - "class T {", - " @Inject T(int x) {}", - " @Inject T() {", - " System.err.println();", - " }", - "}") + "Test.java", + """ + import javax.inject.Inject; + class T { + @Inject T(int x) {} + @Inject T() { + System.err.println(); + } + } + """) .expectUnchanged() .doTest(TEXT_MATCH); } @@ -477,19 +559,23 @@ public void constructor() { public void parameters_withAnnotationsOutOfOrder() { refactoringHelper .addInputLines( - "Test.java", // - "class T {", - " Object foo(@TypeUse @NonTypeUse Object a) {", - " return null;", - " }", - "}") + "Test.java", + """ + class T { + Object foo(@TypeUse @NonTypeUse Object a) { + return null; + } + } + """) .addOutputLines( - "Test.java", // - "class T {", - " Object foo(@NonTypeUse @TypeUse Object a) {", - " return null;", - " }", - "}") + "Test.java", + """ + class T { + Object foo(@NonTypeUse @TypeUse Object a) { + return null; + } + } + """) .doTest(TEXT_MATCH); } @@ -497,19 +583,23 @@ public void parameters_withAnnotationsOutOfOrder() { public void parameters_withInterspersedModifiers() { refactoringHelper .addInputLines( - "Test.java", // - "class T {", - " Object foo(@TypeUse final Object a) {", - " return null;", - " }", - "}") + "Test.java", + """ + class T { + Object foo(@TypeUse final Object a) { + return null; + } + } + """) .addOutputLines( - "Test.java", // - "class T {", - " Object foo(final @TypeUse Object a) {", - " return null;", - " }", - "}") + "Test.java", + """ + class T { + Object foo(final @TypeUse Object a) { + return null; + } + } + """) .doTest(TEXT_MATCH); } @@ -518,13 +608,15 @@ public void varKeyword() { refactoringHelper .addInputLines( "Test.java", - "import com.google.errorprone.annotations.Var;", - "class T {", - " void m() {", - " @Var var x = 1;", - " x = 2;", - " }", - "}") + """ + import com.google.errorprone.annotations.Var; + class T { + void m() { + @Var var x = 1; + x = 2; + } + } + """) .expectUnchanged() .doTest(TEXT_MATCH); } @@ -535,10 +627,12 @@ public void recordAnnotation() { refactoringHelper .addInputLines( "Test.java", - "public record Test(String bar) {", - " @SuppressWarnings(\"unused\")", - " public Test {}", - "}") + """ + public record Test(String bar) { + @SuppressWarnings("unused") + public Test {} + } + """) .expectUnchanged() .doTest(TEXT_MATCH); } @@ -547,19 +641,23 @@ public void recordAnnotation() { public void interspersedJavadoc_enum() { refactoringHelper .addInputLines( - "Test.java", // - "enum Test {", - " @NonTypeUse", - " /** Javadoc! */", - " ONE;", - "}") + "Test.java", + """ + enum Test { + @NonTypeUse + /** Javadoc! */ + ONE; + } + """) .addOutputLines( - "Test.java", // - "enum Test {", - " /** Javadoc! */", - " @NonTypeUse", - " ONE;", - "}") + "Test.java", + """ + enum Test { + /** Javadoc! */ + @NonTypeUse + ONE; + } + """) .doTest(TEXT_MATCH); } @@ -567,19 +665,23 @@ public void interspersedJavadoc_enum() { public void interspersedJavadoc_variableNoModifiers() { refactoringHelper .addInputLines( - "Test.java", // - "class Test {", - " @NonTypeUse", - " /** Javadoc! */", - " int x;", - "}") + "Test.java", + """ + class Test { + @NonTypeUse + /** Javadoc! */ + int x; + } + """) .addOutputLines( - "Test.java", // - "class Test {", - " /** Javadoc! */", - " @NonTypeUse", - " int x;", - "}") + "Test.java", + """ + class Test { + /** Javadoc! */ + @NonTypeUse + int x; + } + """) .doTest(TEXT_MATCH); } @@ -588,20 +690,24 @@ public void variable_genericType_modifiers() { refactoringHelper .addInputLines( "Test.java", - "import java.util.List;", - "class Test {", - " @TypeUse private List x;", - " @EitherUse private List y;", - " @NonTypeUse private List z;", - "}") + """ + import java.util.List; + class Test { + @TypeUse private List x; + @EitherUse private List y; + @NonTypeUse private List z; + } + """) .addOutputLines( "Test.java", - "import java.util.List;", - "class Test {", - " private @TypeUse List x;", - " private @EitherUse List y;", - " @NonTypeUse private List z;", - "}") + """ + import java.util.List; + class Test { + private @TypeUse List x; + private @EitherUse List y; + @NonTypeUse private List z; + } + """) .doTest(TEXT_MATCH); } @@ -612,11 +718,13 @@ public void twoNonTypeAnnotation() { "AnotherNonTypeUse.java", // "@interface AnotherNonTypeUse {}") .addSourceLines( - "Test.java", // - "interface Test {", - " // BUG: Diagnostic contains: [AnnotationPosition] @AnotherNonTypeUse is not", - " @NonTypeUse public @AnotherNonTypeUse void f();", - "}") + "Test.java", + """ + interface Test { + // BUG: Diagnostic contains: [AnnotationPosition] @AnotherNonTypeUse is not + @NonTypeUse public @AnotherNonTypeUse void f(); + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ArrayAsKeyOfSetOrMapTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ArrayAsKeyOfSetOrMapTest.java index 197d60a64c4..eacff83fa5d 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ArrayAsKeyOfSetOrMapTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ArrayAsKeyOfSetOrMapTest.java @@ -39,66 +39,62 @@ public void positive() { compilationHelper .addSourceLines( "Test.java", - "import java.util.Arrays;", - "import java.util.Set;", - "import java.util.Map;", - "import java.util.LinkedHashMap;", - "import java.util.concurrent.ConcurrentHashMap;", - "import com.google.common.collect.Sets;", - "import com.google.common.collect.Maps;", - "import com.google.common.collect.HashMultiset;", - "import com.google.common.collect.LinkedHashMultiset;", - "import com.google.common.collect.HashBiMap;", - "import com.google.common.collect.HashMultimap;", - "import com.google.common.collect.LinkedHashMultimap;", - "import com.google.common.collect.ArrayListMultimap;", - "import com.google.common.collect.LinkedListMultimap;", - "import java.util.HashMap;", - "import java.util.HashSet;", - "class Test{", - " public static void main(String[] args) {", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " Map testNewMap = Maps.newHashMap();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " Set testNewSet = Sets.newHashSet();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " HashMap testNewHashMap = Maps.newHashMap();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " HashSet testNewHashSet = Sets.newHashSet();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " Map testMap = new HashMap();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " Set testSet = new HashSet();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " HashMap testHashMap = new HashMap();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " HashSet testHashSet = new HashSet();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " HashMultimap testHashMultimap = HashMultimap.create();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " ArrayListMultimap testArrayListMultimap" - + " = ArrayListMultimap.create();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " LinkedHashMultimap testLinkedHashMultimap" - + "= LinkedHashMultimap.create();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " LinkedListMultimap testLinkedListMultimap" - + "= LinkedListMultimap.create();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " HashBiMap testHashBiMap = HashBiMap.create();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " LinkedHashMap testLinkedHashMap" - + "= new LinkedHashMap();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " ConcurrentHashMap testConcurrentHashMap" - + "= new ConcurrentHashMap();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " HashMultiset testHashMultiSet = HashMultiset.create();", - " // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap", - " LinkedHashMultiset testLinkedHashMultiSet" - + "= LinkedHashMultiset.create();", - " }", - "}") + """ +import java.util.Arrays; +import java.util.Set; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.concurrent.ConcurrentHashMap; +import com.google.common.collect.Sets; +import com.google.common.collect.Maps; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.LinkedHashMultiset; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.LinkedListMultimap; +import java.util.HashMap; +import java.util.HashSet; +class Test{ + public static void main(String[] args) { + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + Map testNewMap = Maps.newHashMap(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + Set testNewSet = Sets.newHashSet(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + HashMap testNewHashMap = Maps.newHashMap(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + HashSet testNewHashSet = Sets.newHashSet(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + Map testMap = new HashMap(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + Set testSet = new HashSet(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + HashMap testHashMap = new HashMap(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + HashSet testHashSet = new HashSet(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + HashMultimap testHashMultimap = HashMultimap.create(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + ArrayListMultimap testArrayListMultimap = ArrayListMultimap.create(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + LinkedHashMultimap testLinkedHashMultimap= LinkedHashMultimap.create(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + LinkedListMultimap testLinkedListMultimap= LinkedListMultimap.create(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + HashBiMap testHashBiMap = HashBiMap.create(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + LinkedHashMap testLinkedHashMap= new LinkedHashMap(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + ConcurrentHashMap testConcurrentHashMap= new ConcurrentHashMap(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + HashMultiset testHashMultiSet = HashMultiset.create(); + // BUG: Diagnostic contains: ArrayAsKeyOfSetOrMap + LinkedHashMultiset testLinkedHashMultiSet= LinkedHashMultiset.create(); + } +} +""") .doTest(); } @@ -107,53 +103,48 @@ public void negative() { compilationHelper .addSourceLines( "Test.java", - "import java.util.Arrays;", - "import java.util.Set;", - "import java.util.Map;", - "import java.util.LinkedHashMap;", - "import java.util.concurrent.ConcurrentHashMap;", - "import com.google.common.collect.Sets;", - "import com.google.common.collect.Maps;", - "import java.util.HashMap;", - "import java.util.HashSet;", - "import java.util.TreeSet;", - "import com.google.common.collect.HashMultiset;", - "import com.google.common.collect.LinkedHashMultiset;", - "import com.google.common.collect.HashBiMap;", - "import com.google.common.collect.HashMultimap;", - "import com.google.common.collect.LinkedHashMultimap;", - "import com.google.common.collect.ArrayListMultimap;", - "import com.google.common.collect.LinkedListMultimap;", - "import com.google.common.collect.Ordering;", - "class Test {", - " public static void main(String[] args) {", - " Map testMap = new HashMap();", - " Set testSet = new HashSet();", - " HashMap testHashMap = new HashMap();", - " HashSet testHashSet = new HashSet();", - " Set testSet2 = new HashSet();", - " Map testMap2 = new HashMap();", - " Map mapFromMethod = Maps.newHashMap();", - " Set setFromMethod = Sets.newHashSet();", - " Set thisShouldWork = new TreeSet" - + "(Ordering.natural().lexicographical().onResultOf(Arrays::asList));", - " HashMultimap testHashMultimap = HashMultimap.create();", - " ArrayListMultimap testArrayListMultimap" - + " = ArrayListMultimap.create();", - " LinkedHashMultimap testLinkedHashMultimap" - + "= LinkedHashMultimap.create();", - " LinkedListMultimap testLinkedListMultimap" - + "= LinkedListMultimap.create();", - " HashBiMap testHashBiMap = HashBiMap.create();", - " LinkedHashMap testLinkedHashMap" - + "= new LinkedHashMap();", - " ConcurrentHashMap testConcurrentHashMap" - + "= new ConcurrentHashMap();", - " HashMultiset testHashMultiSet = HashMultiset.create();", - " LinkedHashMultiset testLinkedHashMultiSet" - + "= LinkedHashMultiset.create();", - " }", - "}") + """ +import java.util.Arrays; +import java.util.Set; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.concurrent.ConcurrentHashMap; +import com.google.common.collect.Sets; +import com.google.common.collect.Maps; +import java.util.HashMap; +import java.util.HashSet; +import java.util.TreeSet; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.LinkedHashMultiset; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.LinkedListMultimap; +import com.google.common.collect.Ordering; +class Test { + public static void main(String[] args) { + Map testMap = new HashMap(); + Set testSet = new HashSet(); + HashMap testHashMap = new HashMap(); + HashSet testHashSet = new HashSet(); + Set testSet2 = new HashSet(); + Map testMap2 = new HashMap(); + Map mapFromMethod = Maps.newHashMap(); + Set setFromMethod = Sets.newHashSet(); + Set thisShouldWork = new TreeSet(Ordering.natural().lexicographical().onResultOf(Arrays::asList)); + HashMultimap testHashMultimap = HashMultimap.create(); + ArrayListMultimap testArrayListMultimap = ArrayListMultimap.create(); + LinkedHashMultimap testLinkedHashMultimap= LinkedHashMultimap.create(); + LinkedListMultimap testLinkedListMultimap= LinkedListMultimap.create(); + HashBiMap testHashBiMap = HashBiMap.create(); + LinkedHashMap testLinkedHashMap= new LinkedHashMap(); + ConcurrentHashMap testConcurrentHashMap= new ConcurrentHashMap(); + HashMultiset testHashMultiSet = HashMultiset.create(); + LinkedHashMultiset testLinkedHashMultiSet= LinkedHashMultiset.create(); + } +} +""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/BugCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/BugCheckerTest.java index c678d3d2320..acada4c9222 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/BugCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/BugCheckerTest.java @@ -43,29 +43,30 @@ public void isSuppressed_withoutVisitorState() { CompilationTestHelper.newInstance(LegacySuppressionCheck.class, getClass()) .addSourceLines( "A.java", - "class A {", - " void m() {", - " // BUG: Diagnostic contains: []", - " int unsuppressed;", - " // BUG: Diagnostic contains: []", - " @SuppressWarnings(\"foo\") int unrelatedSuppression;", - " // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed]", - " @SuppressWarnings(\"Suppressible\") int suppressed;", - " // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed]", - " @SuppressWarnings(\"Alternative\") int suppressedWithAlternativeName;", - " // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed]", - " @SuppressWarnings(\"all\") int allSuppressed;", - " // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed]", - " @SuppressWarnings({\"foo\", \"Suppressible\"}) int alsoSuppressed;", - " // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed]", - " @SuppressWarnings({\"all\", \"foo\"}) int redundantlySuppressed;", - " // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed]", - " @SuppressWarnings({\"all\", \"OnlySuppressedInsideDeprecatedCode\"}) int" - + " ineffectiveSuppression;", - " // BUG: Diagnostic contains: []", - " @Deprecated int unuspportedSuppression;", - " }", - "}") + """ +class A { + void m() { + // BUG: Diagnostic contains: [] + int unsuppressed; + // BUG: Diagnostic contains: [] + @SuppressWarnings("foo") int unrelatedSuppression; + // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed] + @SuppressWarnings("Suppressible") int suppressed; + // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed] + @SuppressWarnings("Alternative") int suppressedWithAlternativeName; + // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed] + @SuppressWarnings("all") int allSuppressed; + // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed] + @SuppressWarnings({"foo", "Suppressible"}) int alsoSuppressed; + // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed] + @SuppressWarnings({"all", "foo"}) int redundantlySuppressed; + // BUG: Diagnostic contains: [Suppressible, SuppressibleTps, ManualIsSuppressed] + @SuppressWarnings({"all", "OnlySuppressedInsideDeprecatedCode"}) int ineffectiveSuppression; + // BUG: Diagnostic contains: [] + @Deprecated int unuspportedSuppression; + } +} +""") .doTest(); } @@ -74,27 +75,29 @@ public void isSuppressed() { CompilationTestHelper.newInstance(SuppressibleCheck.class, getClass()) .addSourceLines( "A.java", - "class A {", - " void m() {", - " // BUG: Diagnostic contains:", - " int unsuppressed;", - " // BUG: Diagnostic contains:", - " @SuppressWarnings(\"foo\") int unrelatedSuppression;", - " @SuppressWarnings(\"Suppressible\") int suppressed;", - " @SuppressWarnings(\"Alternative\") int suppressedWithAlternativeName;", - " @SuppressWarnings(\"all\") int allSuppressed;", - " @SuppressWarnings({\"foo\", \"Suppressible\"}) int alsoSuppressed;", - " @SuppressWarnings({\"all\", \"foo\"}) int redundantlySuppressed;", - " System.out.println(s(() -> {", - " // BUG: Diagnostic contains: ", - " int insideCalToMethodWhoseDeclarationHasASuppression;", - " }));", - " }", - " @SuppressWarnings(\"all\")", - " String s(Runnable r) {", - " return \"\";", - " }", - "}") + """ + class A { + void m() { + // BUG: Diagnostic contains: + int unsuppressed; + // BUG: Diagnostic contains: + @SuppressWarnings("foo") int unrelatedSuppression; + @SuppressWarnings("Suppressible") int suppressed; + @SuppressWarnings("Alternative") int suppressedWithAlternativeName; + @SuppressWarnings("all") int allSuppressed; + @SuppressWarnings({"foo", "Suppressible"}) int alsoSuppressed; + @SuppressWarnings({"all", "foo"}) int redundantlySuppressed; + System.out.println(s(() -> { + // BUG: Diagnostic contains: + int insideCalToMethodWhoseDeclarationHasASuppression; + })); + } + @SuppressWarnings("all") + String s(Runnable r) { + return ""; + } + } + """) .doTest(); } @@ -103,16 +106,17 @@ public void isSuppressed_customSuppressionAnnotation() { CompilationTestHelper.newInstance(CustomSuppressibilityCheck.class, getClass()) .addSourceLines( "A.java", - "class A {", - " void m() {", - " // BUG: Diagnostic contains:", - " int unsuppressed;", - " // BUG: Diagnostic contains:", - " @SuppressWarnings({\"all\", \"OnlySuppressedInsideDeprecatedCode\"}) int" - + " ineffectiveSuppression;", - " @Deprecated int suppressed;", - " }", - "}") + """ +class A { + void m() { + // BUG: Diagnostic contains: + int unsuppressed; + // BUG: Diagnostic contains: + @SuppressWarnings({"all", "OnlySuppressedInsideDeprecatedCode"}) int ineffectiveSuppression; + @Deprecated int suppressed; + } +} +""") .doTest(); } @@ -121,27 +125,29 @@ public void isSuppressed_suppressibleTreePathScanner() { CompilationTestHelper.newInstance(SuppressibleTreePathScannerCheck.class, getClass()) .addSourceLines( "A.java", - "class A {", - " void m() {", - " // BUG: Diagnostic contains:", - " int unsuppressed;", - " // BUG: Diagnostic contains:", - " @SuppressWarnings(\"foo\") int unrelatedSuppression;", - " @SuppressWarnings(\"Suppressible\") int suppressed;", - " @SuppressWarnings(\"Alternative\") int suppressedWithAlternativeName;", - " @SuppressWarnings(\"all\") int allSuppressed;", - " @SuppressWarnings({\"foo\", \"Suppressible\"}) int alsoSuppressed;", - " @SuppressWarnings({\"all\", \"foo\"}) int redundantlySuppressed;", - " System.out.println(s(() -> {", - " // BUG: Diagnostic contains: ", - " int insideCalToMethodWhoseDeclarationHasASuppression;", - " }));", - " }", - " @SuppressWarnings(\"all\")", - " String s(Runnable r) {", - " return \"\";", - " }", - "}") + """ + class A { + void m() { + // BUG: Diagnostic contains: + int unsuppressed; + // BUG: Diagnostic contains: + @SuppressWarnings("foo") int unrelatedSuppression; + @SuppressWarnings("Suppressible") int suppressed; + @SuppressWarnings("Alternative") int suppressedWithAlternativeName; + @SuppressWarnings("all") int allSuppressed; + @SuppressWarnings({"foo", "Suppressible"}) int alsoSuppressed; + @SuppressWarnings({"all", "foo"}) int redundantlySuppressed; + System.out.println(s(() -> { + // BUG: Diagnostic contains: + int insideCalToMethodWhoseDeclarationHasASuppression; + })); + } + @SuppressWarnings("all") + String s(Runnable r) { + return ""; + } + } + """) .doTest(); } @@ -150,27 +156,29 @@ public void isSuppressed_manualIsSuppressed() { CompilationTestHelper.newInstance(ManuallySuppressibleCheck.class, getClass()) .addSourceLines( "A.java", - "class A {", - " void m() {", - " // BUG: Diagnostic contains:", - " int unsuppressed;", - " // BUG: Diagnostic contains:", - " @SuppressWarnings(\"foo\") int unrelatedSuppression;", - " @SuppressWarnings(\"Suppressible\") int suppressed;", - " @SuppressWarnings(\"Alternative\") int suppressedWithAlternativeName;", - " @SuppressWarnings(\"all\") int allSuppressed;", - " @SuppressWarnings({\"foo\", \"Suppressible\"}) int alsoSuppressed;", - " @SuppressWarnings({\"all\", \"foo\"}) int redundantlySuppressed;", - " System.out.println(s(() -> {", - " // BUG: Diagnostic contains: ", - " int insideCalToMethodWhoseDeclarationHasASuppression;", - " }));", - " }", - " @SuppressWarnings(\"all\")", - " String s(Runnable r) {", - " return \"\";", - " }", - "}") + """ + class A { + void m() { + // BUG: Diagnostic contains: + int unsuppressed; + // BUG: Diagnostic contains: + @SuppressWarnings("foo") int unrelatedSuppression; + @SuppressWarnings("Suppressible") int suppressed; + @SuppressWarnings("Alternative") int suppressedWithAlternativeName; + @SuppressWarnings("all") int allSuppressed; + @SuppressWarnings({"foo", "Suppressible"}) int alsoSuppressed; + @SuppressWarnings({"all", "foo"}) int redundantlySuppressed; + System.out.println(s(() -> { + // BUG: Diagnostic contains: + int insideCalToMethodWhoseDeclarationHasASuppression; + })); + } + @SuppressWarnings("all") + String s(Runnable r) { + return ""; + } + } + """) .doTest(); } @@ -180,13 +188,15 @@ public void isSuppressed_disableWarningsInGeneratedCode() { .setArgs("-XepDisableWarningsInGeneratedCode") .addSourceLines( "A.java", - "import javax.annotation.processing.Generated;", - "class A {", - " void m() {", - " // BUG: Diagnostic contains:", - " @Generated(\"some-tool\") int unsuppressed;", - " }", - "}") + """ + import javax.annotation.processing.Generated; + class A { + void m() { + // BUG: Diagnostic contains: + @Generated("some-tool") int unsuppressed; + } + } + """) .doTest(); // The check is suppressed if its severity is downgraded to `WARNING`. @@ -195,12 +205,14 @@ public void isSuppressed_disableWarningsInGeneratedCode() { "-XepDisableWarningsInGeneratedCode", "-Xep:OnlySuppressedInsideDeprecatedCode:WARN") .addSourceLines( "A.java", - "import javax.annotation.processing.Generated;", - "class A {", - " void m() {", - " @Generated(\"some-tool\") int unsuppressed;", - " }", - "}") + """ + import javax.annotation.processing.Generated; + class A { + void m() { + @Generated("some-tool") int unsuppressed; + } + } + """) .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/CheckReturnValueTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/CheckReturnValueTest.java index 62972c95883..60ce86f3c48 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/CheckReturnValueTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/CheckReturnValueTest.java @@ -55,22 +55,26 @@ public void customCheckReturnValueAnnotation() { compilationHelper .addSourceLines( "foo/bar/CheckReturnValue.java", - "package foo.bar;", - "public @interface CheckReturnValue {}") + """ + package foo.bar; + public @interface CheckReturnValue {} + """) .addSourceLines( "test/TestCustomCheckReturnValueAnnotation.java", - "package test;", - "import foo.bar.CheckReturnValue;", - "public class TestCustomCheckReturnValueAnnotation {", - " @CheckReturnValue", - " public String getString() {", - " return \"string\";", - " }", - " public void doIt() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " getString();", - " }", - "}") + """ + package test; + import foo.bar.CheckReturnValue; + public class TestCustomCheckReturnValueAnnotation { + @CheckReturnValue + public String getString() { + return "string"; + } + public void doIt() { + // BUG: Diagnostic contains: CheckReturnValue + getString(); + } + } + """) .doTest(); } @@ -79,22 +83,26 @@ public void customCanIgnoreReturnValueAnnotation() { compilationHelper .addSourceLines( "foo/bar/CanIgnoreReturnValue.java", - "package foo.bar;", - "public @interface CanIgnoreReturnValue {}") + """ + package foo.bar; + public @interface CanIgnoreReturnValue {} + """) .addSourceLines( "test/TestCustomCanIgnoreReturnValueAnnotation.java", - "package test;", - "import foo.bar.CanIgnoreReturnValue;", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class TestCustomCanIgnoreReturnValueAnnotation {", - " @CanIgnoreReturnValue", - " public String ignored() {", - " return null;", - " }", - " public void doIt() {", - " ignored();", - " }", - "}") + """ + package test; + import foo.bar.CanIgnoreReturnValue; + @com.google.errorprone.annotations.CheckReturnValue + public class TestCustomCanIgnoreReturnValueAnnotation { + @CanIgnoreReturnValue + public String ignored() { + return null; + } + public void doIt() { + ignored(); + } + } + """) .doTest(); } @@ -107,23 +115,29 @@ public void negativeCase() { public void packageAnnotation() { compilationHelper .addSourceLines( - "package-info.java", // - "@com.google.errorprone.annotations.CheckReturnValue", - "package lib;") + "package-info.java", + """ + @com.google.errorprone.annotations.CheckReturnValue + package lib; + """) .addSourceLines( "lib/Lib.java", - "package lib;", - "public class Lib {", - " public static int f() { return 42; }", - "}") + """ + package lib; + public class Lib { + public static int f() { return 42; } + } + """) .addSourceLines( "Test.java", - "class Test {", - " void m() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " lib.Lib.f();", - " }", - "}") + """ + class Test { + void m() { + // BUG: Diagnostic contains: CheckReturnValue + lib.Lib.f(); + } + } + """) .doTest(); } @@ -132,19 +146,23 @@ public void classAnnotation() { compilationHelper .addSourceLines( "lib/Lib.java", - "package lib;", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Lib {", - " public static int f() { return 42; }", - "}") + """ + package lib; + @com.google.errorprone.annotations.CheckReturnValue + public class Lib { + public static int f() { return 42; } + } + """) .addSourceLines( "Test.java", - "class Test {", - " void m() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " lib.Lib.f();", - " }", - "}") + """ + class Test { + void m() { + // BUG: Diagnostic contains: CheckReturnValue + lib.Lib.f(); + } + } + """) .doTest(); } @@ -153,22 +171,28 @@ public void classAnnotation() { public void voidReturningMethodInAnnotatedPackage() { compilationHelper .addSourceLines( - "package-info.java", // - "@com.google.errorprone.annotations.CheckReturnValue", - "package lib;") + "package-info.java", + """ + @com.google.errorprone.annotations.CheckReturnValue + package lib; + """) .addSourceLines( "lib/Lib.java", - "package lib;", - "public class Lib {", - " public static void f() {}", - "}") + """ + package lib; + public class Lib { + public static void f() {} + } + """) .addSourceLines( - "Test.java", // - "class Test {", - " void m() {", - " lib.Lib.f();", - " }", - "}") + "Test.java", + """ + class Test { + void m() { + lib.Lib.f(); + } + } + """) .doTest(); } @@ -177,13 +201,15 @@ public void badCRVOnProcedure() { compilationHelper .addSourceLines( "Test.java", - "package lib;", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Test {", - " // BUG: Diagnostic contains: CheckReturnValue", - " // @CheckReturnValue may not be applied to void-returning methods", - " @com.google.errorprone.annotations.CheckReturnValue public static void f() {}", - "}") + """ + package lib; + @com.google.errorprone.annotations.CheckReturnValue + public class Test { + // BUG: Diagnostic contains: CheckReturnValue + // @CheckReturnValue may not be applied to void-returning methods + @com.google.errorprone.annotations.CheckReturnValue public static void f() {} + } + """) .doTest(); } @@ -192,15 +218,17 @@ public void badCRVOnPseudoProcedure() { compilationHelper .addSourceLines( "Test.java", - "package lib;", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Test {", - " // BUG: Diagnostic contains: CheckReturnValue", - " // @CheckReturnValue may not be applied to void-returning methods", - " @com.google.errorprone.annotations.CheckReturnValue public static Void f() {", - " return null;", - " }", - "}") + """ + package lib; + @com.google.errorprone.annotations.CheckReturnValue + public class Test { + // BUG: Diagnostic contains: CheckReturnValue + // @CheckReturnValue may not be applied to void-returning methods + @com.google.errorprone.annotations.CheckReturnValue public static Void f() { + return null; + } + } + """) .doTest(); } @@ -209,22 +237,28 @@ public void packageAnnotationButCanIgnoreReturnValue() { compilationHelper .addSourceLines( "package-info.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "package lib;") + """ + @com.google.errorprone.annotations.CheckReturnValue + package lib; + """) .addSourceLines( "lib/Lib.java", - "package lib;", - "public class Lib {", - " @com.google.errorprone.annotations.CanIgnoreReturnValue", - " public static int f() { return 42; }", - "}") + """ + package lib; + public class Lib { + @com.google.errorprone.annotations.CanIgnoreReturnValue + public static int f() { return 42; } + } + """) .addSourceLines( - "Test.java", // - "class Test {", - " void m() {", - " lib.Lib.f();", - " }", - "}") + "Test.java", + """ + class Test { + void m() { + lib.Lib.f(); + } + } + """) .doTest(); } @@ -233,19 +267,23 @@ public void classAnnotationButCanIgnoreReturnValue() { compilationHelper .addSourceLines( "lib/Lib.java", - "package lib;", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Lib {", - " @com.google.errorprone.annotations.CanIgnoreReturnValue", - " public static int f() { return 42; }", - "}") + """ + package lib; + @com.google.errorprone.annotations.CheckReturnValue + public class Lib { + @com.google.errorprone.annotations.CanIgnoreReturnValue + public static int f() { return 42; } + } + """) .addSourceLines( - "Test.java", // - "class Test {", - " void m() {", - " lib.Lib.f();", - " }", - "}") + "Test.java", + """ + class Test { + void m() { + lib.Lib.f(); + } + } + """) .doTest(); } @@ -254,13 +292,15 @@ public void badCanIgnoreReturnValueOnProcedure() { compilationHelper .addSourceLines( "Test.java", - "package lib;", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Test {", - " // BUG: Diagnostic contains: CheckReturnValue", - " // @CanIgnoreReturnValue may not be applied to void-returning methods", - " @com.google.errorprone.annotations.CanIgnoreReturnValue public static void f() {}", - "}") + """ + package lib; + @com.google.errorprone.annotations.CheckReturnValue + public class Test { + // BUG: Diagnostic contains: CheckReturnValue + // @CanIgnoreReturnValue may not be applied to void-returning methods + @com.google.errorprone.annotations.CanIgnoreReturnValue public static void f() {} + } + """) .doTest(); } @@ -269,23 +309,27 @@ public void nestedClassAnnotation() { compilationHelper .addSourceLines( "lib/Lib.java", - "package lib;", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Lib {", - " public static class Inner {", - " public static class InnerMost {", - " public static int f() { return 42; }", - " }", - " }", - "}") + """ + package lib; + @com.google.errorprone.annotations.CheckReturnValue + public class Lib { + public static class Inner { + public static class InnerMost { + public static int f() { return 42; } + } + } + } + """) .addSourceLines( "Test.java", - "class Test {", - " void m() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " lib.Lib.Inner.InnerMost.f();", - " }", - "}") + """ + class Test { + void m() { + // BUG: Diagnostic contains: CheckReturnValue + lib.Lib.Inner.InnerMost.f(); + } + } + """) .doTest(); } @@ -294,23 +338,27 @@ public void nestedClassWithCanIgnoreAnnotation() { compilationHelper .addSourceLines( "lib/Lib.java", - "package lib;", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Lib {", - " @com.google.errorprone.annotations.CanIgnoreReturnValue", - " public static class Inner {", - " public static class InnerMost {", - " public static int f() { return 42; }", - " }", - " }", - "}") + """ + package lib; + @com.google.errorprone.annotations.CheckReturnValue + public class Lib { + @com.google.errorprone.annotations.CanIgnoreReturnValue + public static class Inner { + public static class InnerMost { + public static int f() { return 42; } + } + } + } + """) .addSourceLines( "Test.java", - "class Test {", - " void m() {", - " lib.Lib.Inner.InnerMost.f();", - " }", - "}") + """ + class Test { + void m() { + lib.Lib.Inner.InnerMost.f(); + } + } + """) .doTest(); } @@ -319,22 +367,28 @@ public void packageWithCanIgnoreAnnotation() { compilationHelper .addSourceLines( "package-info.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "package lib;") + """ + @com.google.errorprone.annotations.CheckReturnValue + package lib; + """) .addSourceLines( "lib/Lib.java", - "package lib;", - "@com.google.errorprone.annotations.CanIgnoreReturnValue", - "public class Lib {", - " public static int f() { return 42; }", - "}") + """ + package lib; + @com.google.errorprone.annotations.CanIgnoreReturnValue + public class Lib { + public static int f() { return 42; } + } + """) .addSourceLines( - "Test.java", // - "class Test {", - " void m() {", - " lib.Lib.f();", - " }", - "}") + "Test.java", + """ + class Test { + void m() { + lib.Lib.f(); + } + } + """) .doTest(); } @@ -343,11 +397,12 @@ public void errorBothClass() { compilationHelper .addSourceLines( "Test.java", - "@com.google.errorprone.annotations.CanIgnoreReturnValue", - "@com.google.errorprone.annotations.CheckReturnValue", - "// BUG: Diagnostic contains: @CheckReturnValue and @CanIgnoreReturnValue cannot" - + " be applied to the same class", - "class Test {}") + """ +@com.google.errorprone.annotations.CanIgnoreReturnValue +@com.google.errorprone.annotations.CheckReturnValue +// BUG: Diagnostic contains: @CheckReturnValue and @CanIgnoreReturnValue cannot be applied to the same class +class Test {} +""") .doTest(); } @@ -356,13 +411,14 @@ public void errorBothMethod() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " @com.google.errorprone.annotations.CanIgnoreReturnValue", - " @com.google.errorprone.annotations.CheckReturnValue", - " // BUG: Diagnostic contains: @CheckReturnValue and @CanIgnoreReturnValue cannot" - + " be applied to the same method", - " void m() {}", - "}") + """ +class Test { + @com.google.errorprone.annotations.CanIgnoreReturnValue + @com.google.errorprone.annotations.CheckReturnValue + // BUG: Diagnostic contains: @CheckReturnValue and @CanIgnoreReturnValue cannot be applied to the same method + void m() {} +} +""") .doTest(); } @@ -372,23 +428,29 @@ public void javaLangVoidReturningMethodInAnnotatedPackage() { compilationHelper .addSourceLines( "package-info.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "package lib;") + """ + @com.google.errorprone.annotations.CheckReturnValue + package lib; + """) .addSourceLines( "lib/Lib.java", - "package lib;", - "public class Lib {", - " public static Void f() {", - " return null;", - " }", - "}") + """ + package lib; + public class Lib { + public static Void f() { + return null; + } + } + """) .addSourceLines( - "Test.java", // - "class Test {", - " void m() {", - " lib.Lib.f();", - " }", - "}") + "Test.java", + """ + class Test { + void m() { + lib.Lib.f(); + } + } + """) .doTest(); } @@ -397,17 +459,21 @@ public void ignoreVoidReturningMethodReferences() { compilationHelper .addSourceLines( "Lib.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Lib {", - " public static void consume(Object o) {}", - "}") + """ + @com.google.errorprone.annotations.CheckReturnValue + public class Lib { + public static void consume(Object o) {} + } + """) .addSourceLines( "Test.java", - "class Test {", - " void m(java.util.List xs) {", - " xs.forEach(Lib::consume);", - " }", - "}") + """ + class Test { + void m(java.util.List xs) { + xs.forEach(Lib::consume); + } + } + """) .doTest(); } @@ -426,12 +492,14 @@ public void noCRVonClasspath() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " void m() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " com.google.errorprone.bugpatterns.CheckReturnValueTest.CRVTest.f();", - " }", - "}") + """ + class Test { + void m() { + // BUG: Diagnostic contains: CheckReturnValue + com.google.errorprone.bugpatterns.CheckReturnValueTest.CRVTest.f(); + } + } + """) .withClasspath(CRVTest.class, CheckReturnValueTest.class) .doTest(); } @@ -441,14 +509,16 @@ public void constructor() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " @com.google.errorprone.annotations.CheckReturnValue", - " public Test() {}", - " public static void foo() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " new Test();", - " }", - "}") + """ + class Test { + @com.google.errorprone.annotations.CheckReturnValue + public Test() {} + public static void foo() { + // BUG: Diagnostic contains: CheckReturnValue + new Test(); + } + } + """) .doTest(); } @@ -457,14 +527,16 @@ public void constructor_telescoping() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " @com.google.errorprone.annotations.CheckReturnValue", - " public Test() {}", - " public Test(int foo) { this(); }", - " public static void foo() {", - " Test foo = new Test(42);", - " }", - "}") + """ + class Test { + @com.google.errorprone.annotations.CheckReturnValue + public Test() {} + public Test(int foo) { this(); } + public static void foo() { + Test foo = new Test(42); + } + } + """) .doTest(); } @@ -473,14 +545,16 @@ public void constructor_superCall() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " @com.google.errorprone.annotations.CheckReturnValue", - " public Test() {}", - " static class SubTest extends Test { SubTest() { super(); } }", - " public static void foo() {", - " Test derived = new SubTest();", - " }", - "}") + """ + class Test { + @com.google.errorprone.annotations.CheckReturnValue + public Test() {} + static class SubTest extends Test { SubTest() { super(); } } + public static void foo() { + Test derived = new SubTest(); + } + } + """) .doTest(); } @@ -489,14 +563,16 @@ public void constructor_anonymousClassInheritsCIRV() { compilationHelperLookingAtAllConstructors() .addSourceLines( "Test.java", - "class Test {", - " @com.google.errorprone.annotations.CanIgnoreReturnValue", - " public Test() {}", - " public static void foo() {", - " new Test() {};", - " new Test() {{ System.out.println(\"Lookie, instance initializer\"); }};", - " }", - "}") + """ + class Test { + @com.google.errorprone.annotations.CanIgnoreReturnValue + public Test() {} + public static void foo() { + new Test() {}; + new Test() {{ System.out.println("Lookie, instance initializer"); }}; + } + } + """) .doTest(); } @@ -505,14 +581,16 @@ public void constructor_anonymousClassInheritsCRV() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " @com.google.errorprone.annotations.CheckReturnValue", - " public Test() {}", - " public static void foo() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " new Test() {};", - " }", - "}") + """ + class Test { + @com.google.errorprone.annotations.CheckReturnValue + public Test() {} + public static void foo() { + // BUG: Diagnostic contains: CheckReturnValue + new Test() {}; + } + } + """) .doTest(); } @@ -521,16 +599,18 @@ public void constructor_hasOuterInstance() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " class Inner {", - " @com.google.errorprone.annotations.CheckReturnValue", - " public Inner() {}", - " }", - " public static void foo() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " new Test().new Inner() {};", - " }", - "}") + """ + class Test { + class Inner { + @com.google.errorprone.annotations.CheckReturnValue + public Inner() {} + } + public static void foo() { + // BUG: Diagnostic contains: CheckReturnValue + new Test().new Inner() {}; + } + } + """) .doTest(); } @@ -572,19 +652,23 @@ public void constructor_throwingContexts() { compilationHelper .addSourceLines( "Foo.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Foo {}") + """ + @com.google.errorprone.annotations.CheckReturnValue + public class Foo {} + """) .addSourceLines( "Test.java", - "class Test {", - " void f() {", - " try {", - " new Foo();", - " org.junit.Assert.fail();", - " } catch (Exception expected) {}", - " org.junit.Assert.assertThrows(IllegalArgumentException.class, () -> new Foo());", - " }", - "}") + """ + class Test { + void f() { + try { + new Foo(); + org.junit.Assert.fail(); + } catch (Exception expected) {} + org.junit.Assert.assertThrows(IllegalArgumentException.class, () -> new Foo()); + } + } + """) .doTest(); } @@ -593,16 +677,20 @@ public void constructor_reference() { compilationHelper .addSourceLines( "Foo.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "public class Foo {}") + """ + @com.google.errorprone.annotations.CheckReturnValue + public class Foo {} + """) .addSourceLines( "Test.java", - "class Test {", - " void f() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " Runnable ignoresResult = Foo::new;", - " }", - "}") + """ + class Test { + void f() { + // BUG: Diagnostic contains: CheckReturnValue + Runnable ignoresResult = Foo::new; + } + } + """) .doTest(); } @@ -611,13 +699,15 @@ public void constructor_withoutCrvAnnotation() { compilationHelperLookingAtAllConstructors() .addSourceLines( "Test.java", - "class Test {", - " public Test() {}", - " public static void foo() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " new Test();", - " }", - "}") + """ + class Test { + public Test() {} + public static void foo() { + // BUG: Diagnostic contains: CheckReturnValue + new Test(); + } + } + """) .doTest(); } @@ -626,13 +716,15 @@ public void allMethods_withoutCIRVAnnotation() { compilationHelperLookingAtAllMethods() .addSourceLines( "Test.java", - "class Test {", - " public int bar() { return 42; }", - " public static void foo() {", - " // BUG: Diagnostic contains: CheckReturnValue", - " new Test().bar();", - " }", - "}") + """ + class Test { + public int bar() { return 42; } + public static void foo() { + // BUG: Diagnostic contains: CheckReturnValue + new Test().bar(); + } + } + """) .doTest(); } @@ -644,21 +736,25 @@ public void allMethods_withExternallyConfiguredIgnoreList() { compileWithExternalApis("my.java.util.List#add(java.lang.Object)") .addSourceLines( "Test.java", - "import my.java.util.List;", - "class Test {", - " public static void foo(List x) {", - " x.add(42);", - " // BUG: Diagnostic contains: CheckReturnValue", - " x.get(0);", - " }", - "}") + """ + import my.java.util.List; + class Test { + public static void foo(List x) { + x.add(42); + // BUG: Diagnostic contains: CheckReturnValue + x.get(0); + } + } + """) .addSourceLines( "my/java/util/List.java", - "package my.java.util;", - "public interface List {", - " boolean add(E e);", - " E get(int index);", - "}") + """ + package my.java.util; + public interface List { + boolean add(E e); + E get(int index); + } + """) .doTest(); } @@ -667,28 +763,34 @@ public void packagesRule() { compilationHelperWithPackagePatterns("my.java.util") .addSourceLines( "Test.java", - "import my.java.util.List;", - "import my.java.util.regex.Pattern;", - "class Test {", - " public static void foo(List list, Pattern pattern) {", - " // BUG: Diagnostic contains: CheckReturnValue", - " list.get(0);", - " // BUG: Diagnostic contains: CheckReturnValue", - " pattern.matcher(\"blah\");", - " }", - "}") + """ + import my.java.util.List; + import my.java.util.regex.Pattern; + class Test { + public static void foo(List list, Pattern pattern) { + // BUG: Diagnostic contains: CheckReturnValue + list.get(0); + // BUG: Diagnostic contains: CheckReturnValue + pattern.matcher("blah"); + } + } + """) .addSourceLines( "my/java/util/List.java", - "package my.java.util;", - "public interface List {", - " E get(int index);", - "}") + """ + package my.java.util; + public interface List { + E get(int index); + } + """) .addSourceLines( "my/java/util/regex/Pattern.java", - "package my.java.util.regex;", - "public interface Pattern {", - " String matcher(CharSequence input);", - "}") + """ + package my.java.util.regex; + public interface Pattern { + String matcher(CharSequence input); + } + """) .doTest(); } @@ -697,27 +799,33 @@ public void packagesRule_negativePattern() { compilationHelperWithPackagePatterns("my.java.util", "-my.java.util.regex") .addSourceLines( "Test.java", - "import my.java.util.List;", - "import my.java.util.regex.Pattern;", - "class Test {", - " public static void foo(List list, Pattern pattern) {", - " // BUG: Diagnostic contains: CheckReturnValue", - " list.get(0);", - " pattern.matcher(\"blah\");", - " }", - "}") + """ + import my.java.util.List; + import my.java.util.regex.Pattern; + class Test { + public static void foo(List list, Pattern pattern) { + // BUG: Diagnostic contains: CheckReturnValue + list.get(0); + pattern.matcher("blah"); + } + } + """) .addSourceLines( "my/java/util/List.java", - "package my.java.util;", - "public interface List {", - " E get(int index);", - "}") + """ + package my.java.util; + public interface List { + E get(int index); + } + """) .addSourceLines( "my/java/util/regex/Pattern.java", - "package my.java.util.regex;", - "public interface Pattern {", - " String matcher(CharSequence input);", - "}") + """ + package my.java.util.regex; + public interface Pattern { + String matcher(CharSequence input); + } + """) .doTest(); } @@ -729,36 +837,44 @@ public void packagesRule_negativePattern_doesNotMakeOptional() { compilationHelperWithPackagePatterns("my.java.util", "-my.java.util.regex") .addSourceLines( "Test.java", - "import my.java.util.List;", - "import my.java.util.regex.Pattern;", - "import my.java.util.regex.PatternSyntaxException;", - "class Test {", - " public static void foo(List list, Pattern pattern) {", - " // BUG: Diagnostic contains: CheckReturnValue", - " list.get(0);", - " pattern.matcher(\"blah\");", - " // BUG: Diagnostic contains: CheckReturnValue", - " new PatternSyntaxException(\"\", \"\", 0);", - " }", - "}") + """ + import my.java.util.List; + import my.java.util.regex.Pattern; + import my.java.util.regex.PatternSyntaxException; + class Test { + public static void foo(List list, Pattern pattern) { + // BUG: Diagnostic contains: CheckReturnValue + list.get(0); + pattern.matcher("blah"); + // BUG: Diagnostic contains: CheckReturnValue + new PatternSyntaxException("", "", 0); + } + } + """) .addSourceLines( "my/java/util/List.java", - "package my.java.util;", - "public interface List {", - " E get(int index);", - "}") + """ + package my.java.util; + public interface List { + E get(int index); + } + """) .addSourceLines( "my/java/util/regex/Pattern.java", - "package my.java.util.regex;", - "public interface Pattern {", - " String matcher(CharSequence input);", - "}") + """ + package my.java.util.regex; + public interface Pattern { + String matcher(CharSequence input); + } + """) .addSourceLines( "my/java/util/regex/PatternSyntaxException.java", - "package my.java.util.regex;", - "public class PatternSyntaxException extends IllegalArgumentException {", - " public PatternSyntaxException(String desc, String regex, int index) {}", - "}") + """ + package my.java.util.regex; + public class PatternSyntaxException extends IllegalArgumentException { + public PatternSyntaxException(String desc, String regex, int index) {} + } + """) .doTest(); } @@ -767,10 +883,12 @@ public void refactoringAssignsToOriginalBasedOnSubstitutedTypes() { refactoringHelper .addInputLines( "Builder.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "interface Builder> {", - " B setFoo(String s);", - "}") + """ + @com.google.errorprone.annotations.CheckReturnValue + interface Builder> { + B setFoo(String s); + } + """) .expectUnchanged() .addInputLines( "SomeBuilder.java", // @@ -778,18 +896,22 @@ public void refactoringAssignsToOriginalBasedOnSubstitutedTypes() { .expectUnchanged() .addInputLines( "Test.java", - "class Test {", - " void f(SomeBuilder builder, String s) {", - " builder.setFoo(s);", - " }", - "}") + """ + class Test { + void f(SomeBuilder builder, String s) { + builder.setFoo(s); + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " void f(SomeBuilder builder, String s) {", - " builder = builder.setFoo(s);", - " }", - "}") + """ + class Test { + void f(SomeBuilder builder, String s) { + builder = builder.setFoo(s); + } + } + """) .doTest(); } @@ -798,30 +920,34 @@ public void suggestCanIgnoreReturnValueForMethodInvocation() { refactoringHelper .addInputLines( "Test.java", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Test {", - " void foo() {", - " makeBarOrThrow();", - " }", - " String makeBarOrThrow() {", - " throw new UnsupportedOperationException();", - " }", - "}") + """ + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Test { + void foo() { + makeBarOrThrow(); + } + String makeBarOrThrow() { + throw new UnsupportedOperationException(); + } + } + """) .addOutputLines( "Test.java", - "import com.google.errorprone.annotations.CanIgnoreReturnValue;", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Test {", - " void foo() {", - " makeBarOrThrow();", - " }", - " @CanIgnoreReturnValue", - " String makeBarOrThrow() {", - " throw new UnsupportedOperationException();", - " }", - "}") + """ + import com.google.errorprone.annotations.CanIgnoreReturnValue; + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Test { + void foo() { + makeBarOrThrow(); + } + @CanIgnoreReturnValue + String makeBarOrThrow() { + throw new UnsupportedOperationException(); + } + } + """) .doTest(); } @@ -830,26 +956,30 @@ public void suggestCanIgnoreReturnValueForMethodReference() { refactoringHelper .addInputLines( "Test.java", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Test {", - " Runnable r = this::makeBarOrThrow;", - " String makeBarOrThrow() {", - " throw new UnsupportedOperationException();", - " }", - "}") + """ + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Test { + Runnable r = this::makeBarOrThrow; + String makeBarOrThrow() { + throw new UnsupportedOperationException(); + } + } + """) .addOutputLines( "Test.java", - "import com.google.errorprone.annotations.CanIgnoreReturnValue;", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Test {", - " Runnable r = this::makeBarOrThrow;", - " @CanIgnoreReturnValue", - " String makeBarOrThrow() {", - " throw new UnsupportedOperationException();", - " }", - "}") + """ + import com.google.errorprone.annotations.CanIgnoreReturnValue; + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Test { + Runnable r = this::makeBarOrThrow; + @CanIgnoreReturnValue + String makeBarOrThrow() { + throw new UnsupportedOperationException(); + } + } + """) .doTest(); } @@ -858,26 +988,30 @@ public void suggestCanIgnoreReturnValueForConstructor() { refactoringHelper .addInputLines( "Test.java", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Test {", - " Test() {}", - " void run() {", - " new Test();", - " }", - "}") + """ + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Test { + Test() {} + void run() { + new Test(); + } + } + """) .addOutputLines( "Test.java", - "import com.google.errorprone.annotations.CanIgnoreReturnValue;", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Test {", - " @CanIgnoreReturnValue", - " Test() {}", - " void run() {", - " new Test();", - " }", - "}") + """ + import com.google.errorprone.annotations.CanIgnoreReturnValue; + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Test { + @CanIgnoreReturnValue + Test() {} + void run() { + new Test(); + } + } + """) .doTest(); } @@ -886,29 +1020,33 @@ public void suggestCanIgnoreReturnValueAndRemoveCheckReturnValue() { refactoringHelper .addInputLines( "Test.java", - "import com.google.errorprone.annotations.CheckReturnValue;", - "class Test {", - " void foo() {", - " makeBarOrThrow();", - " }", - " @CheckReturnValue", - " String makeBarOrThrow() {", - " throw new UnsupportedOperationException();", - " }", - "}") + """ + import com.google.errorprone.annotations.CheckReturnValue; + class Test { + void foo() { + makeBarOrThrow(); + } + @CheckReturnValue + String makeBarOrThrow() { + throw new UnsupportedOperationException(); + } + } + """) .addOutputLines( "Test.java", - "import com.google.errorprone.annotations.CanIgnoreReturnValue;", - "import com.google.errorprone.annotations.CheckReturnValue;", - "class Test {", - " void foo() {", - " makeBarOrThrow();", - " }", - " @CanIgnoreReturnValue", - " String makeBarOrThrow() {", - " throw new UnsupportedOperationException();", - " }", - "}") + """ + import com.google.errorprone.annotations.CanIgnoreReturnValue; + import com.google.errorprone.annotations.CheckReturnValue; + class Test { + void foo() { + makeBarOrThrow(); + } + @CanIgnoreReturnValue + String makeBarOrThrow() { + throw new UnsupportedOperationException(); + } + } + """) .doTest(); } @@ -917,33 +1055,39 @@ public void doesNotSuggestCanIgnoreReturnValueForOtherFile() { refactoringHelper .addInputLines( "Lib.java", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Lib {", - " String makeBarOrThrow() {", - " throw new UnsupportedOperationException();", - " }", - "}") + """ + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Lib { + String makeBarOrThrow() { + throw new UnsupportedOperationException(); + } + } + """) .expectUnchanged() .addInputLines( "Test.java", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Test {", - " void foo(Lib l) {", - " l.makeBarOrThrow();", - " }", - "}") + """ + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Test { + void foo(Lib l) { + l.makeBarOrThrow(); + } + } + """) // The checker doesn't suggest CIRV, so it applies a different fix instead. .addOutputLines( "Test.java", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "class Test {", - " void foo(Lib l) {", - " var unused = l.makeBarOrThrow();", - " }", - "}") + """ + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + class Test { + void foo(Lib l) { + var unused = l.makeBarOrThrow(); + } + } + """) .doTest(); } @@ -952,20 +1096,24 @@ public void suggestsVarUnusedForConstructor() { refactoringHelper .addInputLines( "Test.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "class Test {", - " void go() {", - " new Test();", - " }", - "}") + """ + @com.google.errorprone.annotations.CheckReturnValue + class Test { + void go() { + new Test(); + } + } + """) .addOutputLines( "Test.java", - "@com.google.errorprone.annotations.CheckReturnValue", - "class Test {", - " void go() {", - " var unused = new Test();", - " }", - "}") + """ + @com.google.errorprone.annotations.CheckReturnValue + class Test { + void go() { + var unused = new Test(); + } + } + """) .doTest(); } @@ -974,29 +1122,35 @@ public void suggestsVarUnused2() { refactoringHelper .addInputLines( "Lib.java", - "import com.google.errorprone.annotations.CheckReturnValue;", - "@CheckReturnValue", - "interface Lib {", - " int a();", - " int b();", - "}") + """ + import com.google.errorprone.annotations.CheckReturnValue; + @CheckReturnValue + interface Lib { + int a(); + int b(); + } + """) .expectUnchanged() .addInputLines( "Test.java", - "class Test {", - " void foo(Lib lib) {", - " var unused = lib.a();", - " lib.b();", - " }", - "}") + """ + class Test { + void foo(Lib lib) { + var unused = lib.a(); + lib.b(); + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " void foo(Lib lib) {", - " var unused = lib.a();", - " var unused2 = lib.b();", - " }", - "}") + """ + class Test { + void foo(Lib lib) { + var unused = lib.a(); + var unused2 = lib.b(); + } + } + """) .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/CompileTimeConstantCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/CompileTimeConstantCheckerTest.java index 44eac0ab581..16009547f11 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/CompileTimeConstantCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/CompileTimeConstantCheckerTest.java @@ -33,13 +33,15 @@ public void matches_fieldAccessFailsWithNonConstant() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public void m(String p, @CompileTimeConstant String q) { }", - " // BUG: Diagnostic contains: Non-compile-time constant expression passed", - " public void r(String s) { this.m(\"boo\", s); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public void m(String p, @CompileTimeConstant String q) { } + // BUG: Diagnostic contains: Non-compile-time constant expression passed + public void r(String s) { this.m("boo", s); } + } + """) .doTest(); } @@ -48,13 +50,15 @@ public void matches_fieldAccessFailsWithNonConstantExpression() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public void m(String p, @CompileTimeConstant String q) { }", - " // BUG: Diagnostic contains: Non-compile-time constant expression passed", - " public void r(String s) { this.m(\"boo\", s +\"boo\"); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public void m(String p, @CompileTimeConstant String q) { } + // BUG: Diagnostic contains: Non-compile-time constant expression passed + public void r(String s) { this.m("boo", s +"boo"); } + } + """) .doTest(); } @@ -63,12 +67,14 @@ public void matches_fieldAccessSucceedsWithLiteral() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public void m(String s, @CompileTimeConstant String p) { }", - " public void r(String x) { this.m(x, \"boo\"); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public void m(String s, @CompileTimeConstant String p) { } + public void r(String x) { this.m(x, "boo"); } + } + """) .doTest(); } @@ -77,13 +83,15 @@ public void matches_fieldAccessSucceedsWithStaticFinal() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static final String S = \"Hello\";", - " public void m(String s, @CompileTimeConstant String p) { }", - " public void r(String x) { this.m(x, S); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static final String S = "Hello"; + public void m(String s, @CompileTimeConstant String p) { } + public void r(String x) { this.m(x, S); } + } + """) .doTest(); } @@ -92,13 +100,15 @@ public void matches_fieldAccessSucceedsWithConstantConcatenation() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static final String S = \"Hello\";", - " public void m(String s, @CompileTimeConstant String p) { }", - " public void r(String x) { this.m(x, S + \" World!\"); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static final String S = "Hello"; + public void m(String s, @CompileTimeConstant String p) { } + public void r(String x) { this.m(x, S + " World!"); } + } + """) .doTest(); } @@ -107,13 +117,15 @@ public void matches_identCallFailsWithNonConstant() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public void m(@CompileTimeConstant String p, int i) { }", - " // BUG: Diagnostic contains: Non-compile-time constant expression passed", - " public void r(String s) { m(s, 19); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public void m(@CompileTimeConstant String p, int i) { } + // BUG: Diagnostic contains: Non-compile-time constant expression passed + public void r(String s) { m(s, 19); } + } + """) .doTest(); } @@ -122,13 +134,15 @@ public void matches_identCallSucceedsWithLiteral() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public void m(String s, @CompileTimeConstant String p) { }", - " public void r(@CompileTimeConstant final String x) { m(x, x); }", - " public void s() { r(\"boo\"); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public void m(String s, @CompileTimeConstant String p) { } + public void r(@CompileTimeConstant final String x) { m(x, x); } + public void s() { r("boo"); } + } + """) .doTest(); } @@ -137,13 +151,15 @@ public void matches_staticCallFailsWithNonConstant() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static void m(@CompileTimeConstant String p, int i) { }", - " // BUG: Diagnostic contains: Non-compile-time constant expression passed", - " public static void r(String s) { m(s, 19); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static void m(@CompileTimeConstant String p, int i) { } + // BUG: Diagnostic contains: Non-compile-time constant expression passed + public static void r(String s) { m(s, 19); } + } + """) .doTest(); } @@ -152,12 +168,14 @@ public void matches_staticCallSucceedsWithLiteral() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static void m(String s, @CompileTimeConstant String p) { }", - " public static void r(String x) { m(x, \"boo\"); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static void m(String s, @CompileTimeConstant String p) { } + public static void r(String x) { m(x, "boo"); } + } + """) .doTest(); } @@ -166,15 +184,17 @@ public void matches_qualifiedStaticCallFailsWithNonConstant() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static class Inner {", - " public static void m(@CompileTimeConstant String p, int i) { }", - " }", - " // BUG: Diagnostic contains: Non-compile-time constant expression passed", - " public static void r(String s) { Inner.m(s, 19); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static class Inner { + public static void m(@CompileTimeConstant String p, int i) { } + } + // BUG: Diagnostic contains: Non-compile-time constant expression passed + public static void r(String s) { Inner.m(s, 19); } + } + """) .doTest(); } @@ -183,14 +203,16 @@ public void matches_qualifiedStaticCallSucceedsWithLiteral() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static class Inner {", - " public static void m(String s, @CompileTimeConstant String p) { }", - " }", - " public static void r(String x) { Inner.m(x, \"boo\"); }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static class Inner { + public static void m(String s, @CompileTimeConstant String p) { } + } + public static void r(String x) { Inner.m(x, "boo"); } + } + """) .doTest(); } @@ -199,15 +221,17 @@ public void matches_ctorSucceedsWithLiteral() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public CompileTimeConstantTestCase(", - " String s, @CompileTimeConstant String p) { }", - " public static CompileTimeConstantTestCase makeNew(String x) {", - " return new CompileTimeConstantTestCase(x, \"boo\");", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public CompileTimeConstantTestCase( + String s, @CompileTimeConstant String p) { } + public static CompileTimeConstantTestCase makeNew(String x) { + return new CompileTimeConstantTestCase(x, "boo"); + } + } + """) .doTest(); } @@ -216,16 +240,18 @@ public void matches_ctorFailsWithNonConstant() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public CompileTimeConstantTestCase(", - " String s, @CompileTimeConstant String p) { }", - " public static CompileTimeConstantTestCase makeNew(String x) {", - " // BUG: Diagnostic contains: Non-compile-time constant expression passed", - " return new CompileTimeConstantTestCase(\"boo\", x);", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public CompileTimeConstantTestCase( + String s, @CompileTimeConstant String p) { } + public static CompileTimeConstantTestCase makeNew(String x) { + // BUG: Diagnostic contains: Non-compile-time constant expression passed + return new CompileTimeConstantTestCase("boo", x); + } + } + """) .doTest(); } @@ -234,16 +260,18 @@ public void matches_identCallSucceedsWithinCtorWithLiteral() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public CompileTimeConstantTestCase(", - " String s, @CompileTimeConstant final String p) { m(p); }", - " public void m(@CompileTimeConstant String r) {}", - " public static CompileTimeConstantTestCase makeNew(String x) {", - " return new CompileTimeConstantTestCase(x, \"boo\");", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public CompileTimeConstantTestCase( + String s, @CompileTimeConstant final String p) { m(p); } + public void m(@CompileTimeConstant String r) {} + public static CompileTimeConstantTestCase makeNew(String x) { + return new CompileTimeConstantTestCase(x, "boo"); + } + } + """) .doTest(); } @@ -276,17 +304,19 @@ public void matches_varargsSuccess() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static void m(String s, @CompileTimeConstant String... p) { }", - " public static void r(String s) { ", - " m(s); ", - " m(s, \"foo\"); ", - " m(s, \"foo\", \"bar\"); ", - " m(s, \"foo\", \"bar\", \"baz\"); ", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static void m(String s, @CompileTimeConstant String... p) { } + public static void r(String s) { + m(s); + m(s, "foo"); + m(s, "foo", "bar"); + m(s, "foo", "bar", "baz"); + } + } + """) .doTest(); } @@ -295,14 +325,16 @@ public void matches_effectivelyFinalCompileTimeConstantParam() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static void m(@CompileTimeConstant String y) { }", - " public static void r(@CompileTimeConstant String x) { ", - " m(x); ", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static void m(@CompileTimeConstant String y) { } + public static void r(@CompileTimeConstant String x) { + m(x); + } + } + """) .doTest(); } @@ -311,16 +343,18 @@ public void matches_nonFinalCompileTimeConstantParam() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " public static void m(@CompileTimeConstant String y) { }", - " public static void r(@CompileTimeConstant String x) { ", - " x = x + \"!\";", - " // BUG: Diagnostic contains: . Did you mean to make 'x' final?", - " m(x); ", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + public static void m(@CompileTimeConstant String y) { } + public static void r(@CompileTimeConstant String x) { + x = x + "!"; + // BUG: Diagnostic contains: . Did you mean to make 'x' final? + m(x); + } + } + """) .doTest(); } @@ -329,15 +363,17 @@ public void matches_override() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "abstract class CompileTimeConstantTestCase {", - " abstract void m(String y);", - " static class C extends CompileTimeConstantTestCase {", - " // BUG: Diagnostic contains: Method with @CompileTimeConstant parameter", - " @Override void m(@CompileTimeConstant String s) {}", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + abstract class CompileTimeConstantTestCase { + abstract void m(String y); + static class C extends CompileTimeConstantTestCase { + // BUG: Diagnostic contains: Method with @CompileTimeConstant parameter + @Override void m(@CompileTimeConstant String s) {} + } + } + """) .doTest(); } @@ -346,16 +382,18 @@ public void matches_methodReference() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "import java.util.function.Consumer;", - "public class CompileTimeConstantTestCase {", - " public static void m(@CompileTimeConstant String s) { }", - " public static Consumer r(String x) {", - " // BUG: Diagnostic contains: Method with @CompileTimeConstant parameter", - " return CompileTimeConstantTestCase::m;", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + import java.util.function.Consumer; + public class CompileTimeConstantTestCase { + public static void m(@CompileTimeConstant String s) { } + public static Consumer r(String x) { + // BUG: Diagnostic contains: Method with @CompileTimeConstant parameter + return CompileTimeConstantTestCase::m; + } + } + """) .doTest(); } @@ -364,16 +402,18 @@ public void matches_constructorReference() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "import java.util.function.Function;", - "public class CompileTimeConstantTestCase {", - " CompileTimeConstantTestCase(@CompileTimeConstant String s) { }", - " public static Function r(String x) {", - " // BUG: Diagnostic contains: Method with @CompileTimeConstant parameter", - " return CompileTimeConstantTestCase::new;", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + import java.util.function.Function; + public class CompileTimeConstantTestCase { + CompileTimeConstantTestCase(@CompileTimeConstant String s) { } + public static Function r(String x) { + // BUG: Diagnostic contains: Method with @CompileTimeConstant parameter + return CompileTimeConstantTestCase::new; + } + } + """) .doTest(); } @@ -382,18 +422,20 @@ public void matches_methodReferenceCorrectOverrideMethod() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "import java.util.function.Consumer;", - "public class CompileTimeConstantTestCase {", - " interface ConstantFn {", - " void apply(@CompileTimeConstant String s);", - " }", - " public static void m(@CompileTimeConstant String s) { }", - " public static ConstantFn r(String x) {", - " return CompileTimeConstantTestCase::m;", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + import java.util.function.Consumer; + public class CompileTimeConstantTestCase { + interface ConstantFn { + void apply(@CompileTimeConstant String s); + } + public static void m(@CompileTimeConstant String s) { } + public static ConstantFn r(String x) { + return CompileTimeConstantTestCase::m; + } + } + """) .doTest(); } @@ -402,18 +444,20 @@ public void matches_methodReferenceCorrectOverrideConstructor() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "import java.util.function.Consumer;", - "public class CompileTimeConstantTestCase {", - " interface ConstantFn {", - " CompileTimeConstantTestCase apply(@CompileTimeConstant String s);", - " }", - " CompileTimeConstantTestCase(@CompileTimeConstant String s) {}", - " public static ConstantFn r(String x) {", - " return CompileTimeConstantTestCase::new;", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + import java.util.function.Consumer; + public class CompileTimeConstantTestCase { + interface ConstantFn { + CompileTimeConstantTestCase apply(@CompileTimeConstant String s); + } + CompileTimeConstantTestCase(@CompileTimeConstant String s) {} + public static ConstantFn r(String x) { + return CompileTimeConstantTestCase::new; + } + } + """) .doTest(); } @@ -422,13 +466,15 @@ public void matches_lambdaExpression() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "import java.util.function.Consumer;", - "public class CompileTimeConstantTestCase {", - " // BUG: Diagnostic contains: Method with @CompileTimeConstant parameter", - " Consumer c = (@CompileTimeConstant String s) -> {};", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + import java.util.function.Consumer; + public class CompileTimeConstantTestCase { + // BUG: Diagnostic contains: Method with @CompileTimeConstant parameter + Consumer c = (@CompileTimeConstant String s) -> {}; + } + """) .doTest(); } @@ -437,16 +483,18 @@ public void doesNotMatch_lambdaExpression_correctOverride() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "import java.util.function.Consumer;", - "public class CompileTimeConstantTestCase {", - " interface ConstantFn {", - " void apply(@CompileTimeConstant String s);", - " }", - " ConstantFn c = (@CompileTimeConstant String s) -> {doFoo(s);};", - " void doFoo(final @CompileTimeConstant String foo) {}", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + import java.util.function.Consumer; + public class CompileTimeConstantTestCase { + interface ConstantFn { + void apply(@CompileTimeConstant String s); + } + ConstantFn c = (@CompileTimeConstant String s) -> {doFoo(s);}; + void doFoo(final @CompileTimeConstant String foo) {} + } + """) .doTest(); } @@ -455,17 +503,19 @@ public void matches_lambdaExpressionWithoutAnnotatedParameters() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "import java.util.function.Consumer;", - "public class CompileTimeConstantTestCase {", - " interface ConstantFn {", - " void apply(@CompileTimeConstant String s);", - " }", - " // BUG: Diagnostic contains: Non-compile-time constant expression", - " ConstantFn c = s -> {doFoo(s);};", - " void doFoo(final @CompileTimeConstant String foo) {}", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + import java.util.function.Consumer; + public class CompileTimeConstantTestCase { + interface ConstantFn { + void apply(@CompileTimeConstant String s); + } + // BUG: Diagnostic contains: Non-compile-time constant expression + ConstantFn c = s -> {doFoo(s);}; + void doFoo(final @CompileTimeConstant String foo) {} + } + """) .doTest(); } @@ -474,19 +524,21 @@ public void matches_lambdaExpressionWithoutExplicitFormalParameters() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " @FunctionalInterface", - " interface I {", - " void f(@CompileTimeConstant String x);", - " }", - " void f(String s) {", - " I i = x -> {};", - " // BUG: Diagnostic contains: Non-compile-time constant expression passed", - " i.f(s);", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + @FunctionalInterface + interface I { + void f(@CompileTimeConstant String x); + } + void f(String s) { + I i = x -> {}; + // BUG: Diagnostic contains: Non-compile-time constant expression passed + i.f(s); + } + } + """) .doTest(); } @@ -495,12 +547,14 @@ public void reportsDiagnostic_whenConstantFieldDeclaredWithoutFinal() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " // BUG: Diagnostic contains: . Did you mean to make 's' final?", - " @CompileTimeConstant String s = \"s\";", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + // BUG: Diagnostic contains: . Did you mean to make 's' final? + @CompileTimeConstant String s = "s"; + } + """) .doTest(); } @@ -509,11 +563,13 @@ public void noDiagnostic_whenConstantFieldDeclaredFinal() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " @CompileTimeConstant final String s = \"s\";", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + @CompileTimeConstant final String s = "s"; + } + """) .doTest(); } @@ -522,15 +578,17 @@ public void reportsDiagnostic_whenInitialisingFinalFieldWithNonConstant() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " @CompileTimeConstant final String s;", - " CompileTimeConstantTestCase(String s) {", - " // BUG: Diagnostic contains: Non-compile-time constant expression", - " this.s = s;", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + @CompileTimeConstant final String s; + CompileTimeConstantTestCase(String s) { + // BUG: Diagnostic contains: Non-compile-time constant expression + this.s = s; + } + } + """) .doTest(); } @@ -539,14 +597,16 @@ public void noDiagnostic_whenInitialisingFinalFieldWithConstant() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " @CompileTimeConstant final String s;", - " CompileTimeConstantTestCase(@CompileTimeConstant String s) {", - " this.s = s;", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + @CompileTimeConstant final String s; + CompileTimeConstantTestCase(@CompileTimeConstant String s) { + this.s = s; + } + } + """) .doTest(); } @@ -555,18 +615,20 @@ public void noDiagnostic_whenInvokingMethodWithFinalField() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public class CompileTimeConstantTestCase {", - " @CompileTimeConstant final String s;", - " CompileTimeConstantTestCase(@CompileTimeConstant String s) {", - " this.s = s;", - " }", - " void invokeCTCMethod() {", - " ctcMethod(s);", - " }", - " void ctcMethod(@CompileTimeConstant String s) {}", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public class CompileTimeConstantTestCase { + @CompileTimeConstant final String s; + CompileTimeConstantTestCase(@CompileTimeConstant String s) { + this.s = s; + } + void invokeCTCMethod() { + ctcMethod(s); + } + void ctcMethod(@CompileTimeConstant String s) {} + } + """) .doTest(); } @@ -575,15 +637,17 @@ public void reportsDiagnostic_whenConstantEnumFieldDeclaredWithoutFinal() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public enum Test {", - " A(\"A\");", - " // BUG: Diagnostic contains: . Did you mean to make 's' final?", - " @CompileTimeConstant String s;", - " Test(@CompileTimeConstant String s) {", - " this.s = s;", - " }", - "}") + """ + import com.google.errorprone.annotations.CompileTimeConstant; + public enum Test { + A("A"); + // BUG: Diagnostic contains: . Did you mean to make 's' final? + @CompileTimeConstant String s; + Test(@CompileTimeConstant String s) { + this.s = s; + } + } + """) .doTest(); } @@ -592,14 +656,16 @@ public void noDiagnostic_whenConstantEnumFieldDeclaredFinal() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public enum Test {", - " A(\"A\");", - " @CompileTimeConstant final String s;", - " Test(@CompileTimeConstant String s) {", - " this.s = s;", - " }", - "}") + """ + import com.google.errorprone.annotations.CompileTimeConstant; + public enum Test { + A("A"); + @CompileTimeConstant final String s; + Test(@CompileTimeConstant String s) { + this.s = s; + } + } + """) .doTest(); } @@ -608,15 +674,17 @@ public void reportsDiagnostic_whenInitialisingFinalEnumFieldWithNonConstant() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public enum Test {", - " A(\"A\");", - " @CompileTimeConstant final String s;", - " Test(String s) {", - " // BUG: Diagnostic contains: Non-compile-time constant expression", - " this.s = s;", - " }", - "}") + """ + import com.google.errorprone.annotations.CompileTimeConstant; + public enum Test { + A("A"); + @CompileTimeConstant final String s; + Test(String s) { + // BUG: Diagnostic contains: Non-compile-time constant expression + this.s = s; + } + } + """) .doTest(); } @@ -625,18 +693,20 @@ public void noDiagnostic_whenInvokingMethodWithFinalEnumField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public enum Test {", - " A(\"A\");", - " @CompileTimeConstant final String s;", - " Test(@CompileTimeConstant String s) {", - " this.s = s;", - " }", - " void invokeCTCMethod() {", - " ctcMethod(s);", - " }", - " void ctcMethod(@CompileTimeConstant String s) {}", - "}") + """ + import com.google.errorprone.annotations.CompileTimeConstant; + public enum Test { + A("A"); + @CompileTimeConstant final String s; + Test(@CompileTimeConstant String s) { + this.s = s; + } + void invokeCTCMethod() { + ctcMethod(s); + } + void ctcMethod(@CompileTimeConstant String s) {} + } + """) .doTest(); } @@ -645,13 +715,15 @@ public void nonConstantField_positive() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public abstract class CompileTimeConstantTestCase {", - " abstract String something();", - " // BUG: Diagnostic contains: Non-compile-time constant expression", - " @CompileTimeConstant final String x = something();", - "}") + """ + package test; + import com.google.errorprone.annotations.CompileTimeConstant; + public abstract class CompileTimeConstantTestCase { + abstract String something(); + // BUG: Diagnostic contains: Non-compile-time constant expression + @CompileTimeConstant final String x = something(); + } + """) .doTest(); } @@ -660,12 +732,14 @@ public void constantField_immutableList() { compilationHelper .addSourceLines( "test/CompileTimeConstantTestCase.java", - "package test;", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.CompileTimeConstant;", - "public abstract class CompileTimeConstantTestCase {", - " @CompileTimeConstant final ImmutableList x = ImmutableList.of(\"a\");", - "}") + """ + package test; + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.CompileTimeConstant; + public abstract class CompileTimeConstantTestCase { + @CompileTimeConstant final ImmutableList x = ImmutableList.of("a"); + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ConstantOverflowTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ConstantOverflowTest.java index 3d3addac2a8..d9a8191263a 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ConstantOverflowTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ConstantOverflowTest.java @@ -34,20 +34,22 @@ public void positiveExpressions() { testHelper .addSourceLines( "Test.java", - "class Test {", - " static final int C = 1;", - " void g(int x) {}", - " void f() {", - " // BUG: Diagnostic contains: if (1000L * 1000 * 1000 * 10 * 1L == 0);", - " if (1000 * 1000 * 1000 * 10 * 1L == 0);", - " // BUG: Diagnostic contains: int x = (int) (1000L * 1000 * 1000 * 10 * 1L);", - " int x = (int) (1000 * 1000 * 1000 * 10 * 1L);", - " // BUG: Diagnostic contains: long y = 1000L * 1000 * 1000 * 10;", - " int y = 1000 * 1000 * 1000 * 10;", - " // BUG: Diagnostic contains:", - " g(C * 1000 * 1000 * 1000 * 10);", - " }", - "}") + """ + class Test { + static final int C = 1; + void g(int x) {} + void f() { + // BUG: Diagnostic contains: if (1000L * 1000 * 1000 * 10 * 1L == 0); + if (1000 * 1000 * 1000 * 10 * 1L == 0); + // BUG: Diagnostic contains: int x = (int) (1000L * 1000 * 1000 * 10 * 1L); + int x = (int) (1000 * 1000 * 1000 * 10 * 1L); + // BUG: Diagnostic contains: long y = 1000L * 1000 * 1000 * 10; + int y = 1000 * 1000 * 1000 * 10; + // BUG: Diagnostic contains: + g(C * 1000 * 1000 * 1000 * 10); + } + } + """) .doTest(); } @@ -56,15 +58,17 @@ public void positiveFields() { testHelper .addSourceLines( "Test.java", - "class Test {", - " // BUG: Diagnostic contains: Long a = 1000L * 1000 * 1000 * 10 * 1L;", - " Long a = 1000 * 1000 * 1000 * 10 * 1L;", - " // BUG: Diagnostic contains:", - " int b = (int) 24L * 60 * 60 * 1000 * 1000;", - " long c = (long) 24L * 60 * 60 * 1000 * 1000;", - " // BUG: Diagnostic contains: long d = 24L * 60 * 60 * 1000 * 1000;", - " long d = 24 * 60 * 60 * 1000 * 1000;", - "}") + """ + class Test { + // BUG: Diagnostic contains: Long a = 1000L * 1000 * 1000 * 10 * 1L; + Long a = 1000 * 1000 * 1000 * 10 * 1L; + // BUG: Diagnostic contains: + int b = (int) 24L * 60 * 60 * 1000 * 1000; + long c = (long) 24L * 60 * 60 * 1000 * 1000; + // BUG: Diagnostic contains: long d = 24L * 60 * 60 * 1000 * 1000; + long d = 24 * 60 * 60 * 1000 * 1000; + } + """) .doTest(); } @@ -72,10 +76,12 @@ public void positiveFields() { public void negativeFloat() { testHelper .addSourceLines( - "Test.java", // - "class Test {", - " public static final int a = (int) (10 / 0.5);", - "}") + "Test.java", + """ + class Test { + public static final int a = (int) (10 / 0.5); + } + """) .doTest(); } @@ -84,11 +90,13 @@ public void negativeCharCast() { testHelper .addSourceLines( "Test.java", - "class Test {", - " public static final char a = (char) Integer.MAX_VALUE;", - " public static final char b = (char) -1;", - " public static final char c = (char) 1;", - "}") + """ + class Test { + public static final char a = (char) Integer.MAX_VALUE; + public static final char b = (char) -1; + public static final char c = (char) 1; + } + """) .doTest(); } @@ -97,13 +105,15 @@ public void negativeCast() { testHelper .addSourceLines( "Test.java", - "class Test {", - " public static final byte a = (byte) 1;", - " private static final byte b = (byte) 0b1000_0000;", - " private static final byte c = (byte) 0x80;", - " private static final byte d = (byte) 0xfff;", - " private static final byte e = (byte) -1;", - "}") + """ + class Test { + public static final byte a = (byte) 1; + private static final byte b = (byte) 0b1000_0000; + private static final byte c = (byte) 0x80; + private static final byte d = (byte) 0xfff; + private static final byte e = (byte) -1; + } + """) .doTest(); } @@ -111,10 +121,12 @@ public void negativeCast() { public void negative() { testHelper .addSourceLines( - "Test.java", // - "class Test {", - " long microDay = 24L * 60 * 60 * 1000 * 1000;", - "}") + "Test.java", + """ + class Test { + long microDay = 24L * 60 * 60 * 1000 * 1000; + } + """) .doTest(); } @@ -123,14 +135,16 @@ public void bitAnd() { testHelper .addSourceLines( "Test.java", - "class Test {", - " private static final int MASK = (1 << 31);", - " void f(int[] xs) {", - " for (final int x : xs) {", - " final int y = (x & (MASK - 1));", - " }", - " }", - "}") + """ + class Test { + private static final int MASK = (1 << 31); + void f(int[] xs) { + for (final int x : xs) { + final int y = (x & (MASK - 1)); + } + } + } + """) .doTest(); } @@ -139,28 +153,44 @@ public void longOverflow() { BugCheckerRefactoringTestHelper.newInstance(ConstantOverflow.class, getClass()) .addInputLines( "in/Test.java", - "class Test {", - " private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L;", - " void f() {", - " System.err.println(2 * GOLDEN_GAMMA);", - " }", - "}") + """ + class Test { + private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L; + void f() { + System.err.println(2 * GOLDEN_GAMMA); + } + } + """) .addOutputLines( "out/Test.java", - "class Test {", - " private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L;", - " void f() {", - " System.err.println(2 * GOLDEN_GAMMA);", - " }", - "}") + """ + class Test { + private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L; + void f() { + System.err.println(2 * GOLDEN_GAMMA); + } + } + """) .doTest(); } @Test public void onlyFixIntegers() { BugCheckerRefactoringTestHelper.newInstance(ConstantOverflow.class, getClass()) - .addInputLines("in/Test.java", "class Test {", " int a = 'a' + Integer.MAX_VALUE;", "}") - .addOutputLines("out/Test.java", "class Test {", " int a = 'a' + Integer.MAX_VALUE;", "}") + .addInputLines( + "in/Test.java", + """ + class Test { + int a = 'a' + Integer.MAX_VALUE; + } + """) + .addOutputLines( + "out/Test.java", + """ + class Test { + int a = 'a' + Integer.MAX_VALUE; + } + """) .doTest(); } @@ -168,19 +198,23 @@ public void onlyFixIntegers() { public void varType() { BugCheckerRefactoringTestHelper.newInstance(ConstantOverflow.class, getClass()) .addInputLines( - "Test.java", // - "class Test {", - " void f() {", - " var x = 1 + Integer.MAX_VALUE;", - " }", - "}") + "Test.java", + """ + class Test { + void f() { + var x = 1 + Integer.MAX_VALUE; + } + } + """) .addOutputLines( - "Test.java", // - "class Test {", - " void f() {", - " var x = 1L + Integer.MAX_VALUE;", - " }", - "}") + "Test.java", + """ + class Test { + void f() { + var x = 1L + Integer.MAX_VALUE; + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/DoNotCallCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/DoNotCallCheckerTest.java index f67d7532730..2e9181bdd6d 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/DoNotCallCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/DoNotCallCheckerTest.java @@ -41,22 +41,24 @@ public void positive() { testHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.DoNotCall;", - "class Test {", - " @DoNotCall(\"satisfying explanation\") final void f() {}", - " @DoNotCall final void g() {}", - " void m() {", - " // BUG: Diagnostic contains:", - " // Test.f() should not be called: satisfying explanation", - " f();", - " // BUG: Diagnostic contains:", - " // Test.g() should not be called, see its documentation for details.", - " g();", - " // BUG: Diagnostic contains:", - " // Test.g() should not be called, see its documentation for details.", - " Runnable r = this::g;", - " }", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + class Test { + @DoNotCall("satisfying explanation") final void f() {} + @DoNotCall final void g() {} + void m() { + // BUG: Diagnostic contains: + // Test.f() should not be called: satisfying explanation + f(); + // BUG: Diagnostic contains: + // Test.g() should not be called, see its documentation for details. + g(); + // BUG: Diagnostic contains: + // Test.g() should not be called, see its documentation for details. + Runnable r = this::g; + } + } + """) .doTest(); } @@ -65,15 +67,17 @@ public void positiveWhereDeclaredTypeIsSuper() { testHelperWithImmutableList() .addSourceLines( "Test.java", - "import java.util.List;", - "class Test {", - " void foo() {", - " List xs = ImmutableList.of();", - " // BUG: Diagnostic contains:", - " xs.add(1);", - " xs.get(1);", - " }", - "}") + """ + import java.util.List; + class Test { + void foo() { + List xs = ImmutableList.of(); + // BUG: Diagnostic contains: + xs.add(1); + xs.get(1); + } + } + """) .doTest(); } @@ -82,20 +86,22 @@ public void positiveWhereDeclaredTypeIsSuper_butAssignedMultipleTimes() { testHelperWithImmutableList() .addSourceLines( "Test.java", - "import java.util.List;", - "class Test {", - " void foo() {", - " List xs;", - " if (hashCode() == 0) {", - " xs = ImmutableList.of();", - " } else {", - " xs = ImmutableList.of();", - " }", - " // BUG: Diagnostic contains:", - " xs.add(1);", - " xs.get(1);", - " }", - "}") + """ + import java.util.List; + class Test { + void foo() { + List xs; + if (hashCode() == 0) { + xs = ImmutableList.of(); + } else { + xs = ImmutableList.of(); + } + // BUG: Diagnostic contains: + xs.add(1); + xs.get(1); + } + } + """) .doTest(); } @@ -104,21 +110,24 @@ private CompilationTestHelper testHelperWithImmutableList() { return testHelper .addSourceLines( "ImmutableCollection.java", - "import com.google.errorprone.annotations.DoNotCall;", - "import java.util.List;", - "abstract class ImmutableCollection implements java.util.Collection {", - " @DoNotCall @Override public final boolean add(T t) { throw new" - + " UnsupportedOperationException(); }", - "}") + """ +import com.google.errorprone.annotations.DoNotCall; +import java.util.List; +abstract class ImmutableCollection implements java.util.Collection { + @DoNotCall @Override public final boolean add(T t) { throw new UnsupportedOperationException(); } +} +""") .addSourceLines( "ImmutableList.java", - "import com.google.errorprone.annotations.DoNotCall;", - "import java.util.List;", - "abstract class ImmutableList extends ImmutableCollection implements List {", - " public static ImmutableList of() {", - " return null;", - " }", - "}"); + """ + import com.google.errorprone.annotations.DoNotCall; + import java.util.List; + abstract class ImmutableList extends ImmutableCollection implements List { + public static ImmutableList of() { + return null; + } + } + """); } @Test @@ -126,20 +135,22 @@ public void positiveWhereDeclaredTypeIsSuper_butNotAssignedOnce() { testHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "import java.util.ArrayList;", - "import java.util.List;", - "class Test {", - " void foo() {", - " List xs;", - " if (true) {", - " xs = ImmutableList.of();", - " } else {", - " xs = new ArrayList<>();", - " xs.add(2);", - " }", - " }", - "}") + """ + import com.google.common.collect.ImmutableList; + import java.util.ArrayList; + import java.util.List; + class Test { + void foo() { + List xs; + if (true) { + xs = ImmutableList.of(); + } else { + xs = new ArrayList<>(); + xs.add(2); + } + } + } + """) .doTest(); } @@ -148,12 +159,14 @@ public void concreteFinal() { testHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.DoNotCall;", - "public class Test {", - " // BUG: Diagnostic contains: should be final", - " @DoNotCall public void f() {}", - " @DoNotCall public final void g() {}", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + public class Test { + // BUG: Diagnostic contains: should be final + @DoNotCall public void f() {} + @DoNotCall public final void g() {} + } + """) .doTest(); } @@ -162,16 +175,20 @@ public void requiredOverride() { testHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.DoNotCall;", - "public interface A {", - " @DoNotCall public void f();", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + public interface A { + @DoNotCall public void f(); + } + """) .addSourceLines( "B.java", - "public class B implements A {", - " // BUG: Diagnostic contains: overrides f in A which is annotated", - " @Override public void f() {}", - "}") + """ + public class B implements A { + // BUG: Diagnostic contains: overrides f in A which is annotated + @Override public void f() {} + } + """) .doTest(); } @@ -180,16 +197,20 @@ public void annotatedOverride() { testHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.DoNotCall;", - "public interface A {", - " @DoNotCall public void f();", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + public interface A { + @DoNotCall public void f(); + } + """) .addSourceLines( "B.java", - "import com.google.errorprone.annotations.DoNotCall;", - "public class B implements A {", - " @DoNotCall @Override public final void f() {}", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + public class B implements A { + @DoNotCall @Override public final void f() {} + } + """) .doTest(); } @@ -204,24 +225,30 @@ public void interfaceRedeclaresObjectMethod() { testHelper .addSourceLines( "I.java", - "import com.google.errorprone.annotations.DoNotCall;", - "public interface I {", - " @DoNotCall public String toString();", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + public interface I { + @DoNotCall public String toString(); + } + """) .addSourceLines( - "B.java", // - "public class B implements I {", - "}") + "B.java", + """ + public class B implements I { + } + """) .addSourceLines( - "Test.java", // - "public class Test {", - " void f(B b) {", - " b.toString();", - " I i = b;", - " // BUG: Diagnostic contains:", - " i.toString();", - " }", - "}") + "Test.java", + """ + public class Test { + void f(B b) { + b.toString(); + I i = b; + // BUG: Diagnostic contains: + i.toString(); + } + } + """) .doTest(); } @@ -230,10 +257,12 @@ public void finalClass() { testHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.DoNotCall;", - "public final class Test {", - " @DoNotCall public void f() {}", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + public final class Test { + @DoNotCall public void f() {} + } + """) .doTest(); } @@ -242,11 +271,13 @@ public void privateMethod() { testHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.DoNotCall;", - "public final class Test {", - " // BUG: Diagnostic contains: private method", - " @DoNotCall private void f() {}", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + public final class Test { + // BUG: Diagnostic contains: private method + @DoNotCall private void f() {} + } + """) .doTest(); } @@ -263,14 +294,14 @@ public void noDNConClasspath() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void m() {", - " // BUG: Diagnostic contains:" - + " com.google.errorprone.bugpatterns.DoNotCallCheckerTest.DNCTest.f() should not" - + " be called, see its documentation for details.", - " com.google.errorprone.bugpatterns.DoNotCallCheckerTest.DNCTest.f();", - " }", - "}") + """ +class Test { + void m() { + // BUG: Diagnostic contains: com.google.errorprone.bugpatterns.DoNotCallCheckerTest.DNCTest.f() should not be called, see its documentation for details. + com.google.errorprone.bugpatterns.DoNotCallCheckerTest.DNCTest.f(); + } +} +""") .withClasspath(DNCTest.class, DoNotCallCheckerTest.class) .doTest(); } @@ -301,14 +332,16 @@ public void javaSqlDate_toInstant() { testHelper .addSourceLines( "TestClass.java", - "import java.sql.Date;", - "import java.time.Instant;", - "public class TestClass {", - " public void badApis(Date date) {", - " // BUG: Diagnostic contains: toLocalDate()", - " Instant instant = date.toInstant();", - " }", - "}") + """ + import java.sql.Date; + import java.time.Instant; + public class TestClass { + public void badApis(Date date) { + // BUG: Diagnostic contains: toLocalDate() + Instant instant = date.toInstant(); + } + } + """) .doTest(); } @@ -321,17 +354,19 @@ public void javaSqlDate_timeGetters() { testHelper .addSourceLines( "TestClass.java", - "import java.sql.Date;", - "public class TestClass {", - " public void badApis(Date date) {", - " // BUG: Diagnostic contains: DoNotCall", - " int hour = date.getHours();", - " // BUG: Diagnostic contains: DoNotCall", - " int mins = date.getMinutes();", - " // BUG: Diagnostic contains: DoNotCall", - " int secs = date.getSeconds();", - " }", - "}") + """ + import java.sql.Date; + public class TestClass { + public void badApis(Date date) { + // BUG: Diagnostic contains: DoNotCall + int hour = date.getHours(); + // BUG: Diagnostic contains: DoNotCall + int mins = date.getMinutes(); + // BUG: Diagnostic contains: DoNotCall + int secs = date.getSeconds(); + } + } + """) .doTest(); } @@ -344,17 +379,19 @@ public void javaSqlDate_timeSetters() { testHelper .addSourceLines( "TestClass.java", - "import java.sql.Date;", - "public class TestClass {", - " public void badApis(Date date) {", - " // BUG: Diagnostic contains: DoNotCall", - " date.setHours(1);", - " // BUG: Diagnostic contains: DoNotCall", - " date.setMinutes(1);", - " // BUG: Diagnostic contains: DoNotCall", - " date.setSeconds(1);", - " }", - "}") + """ + import java.sql.Date; + public class TestClass { + public void badApis(Date date) { + // BUG: Diagnostic contains: DoNotCall + date.setHours(1); + // BUG: Diagnostic contains: DoNotCall + date.setMinutes(1); + // BUG: Diagnostic contains: DoNotCall + date.setSeconds(1); + } + } + """) .doTest(); } @@ -363,20 +400,22 @@ public void javaSqlDate_staticallyTypedAsJavaUtilDate() { testHelper .addSourceLines( "TestClass.java", - "import java.time.Instant;", - "import java.util.Date;", - "public class TestClass {", - " public void badApis() {", - " Date date = new java.sql.Date(1234567890L);", - " Instant instant = date.toInstant();", - " int hour = date.getHours();", - " int mins = date.getMinutes();", - " int secs = date.getSeconds();", - " date.setHours(1);", - " date.setMinutes(1);", - " date.setSeconds(1);", - " }", - "}") + """ + import java.time.Instant; + import java.util.Date; + public class TestClass { + public void badApis() { + Date date = new java.sql.Date(1234567890L); + Instant instant = date.toInstant(); + int hour = date.getHours(); + int mins = date.getMinutes(); + int secs = date.getSeconds(); + date.setHours(1); + date.setMinutes(1); + date.setSeconds(1); + } + } + """) .doTest(); } @@ -386,14 +425,16 @@ public void javaSqlTime_toInstant() { testHelper .addSourceLines( "TestClass.java", - "import java.sql.Time;", - "import java.time.Instant;", - "public class TestClass {", - " public void badApis(Time time) {", - " // BUG: Diagnostic contains: toLocalTime()", - " Instant instant = time.toInstant();", - " }", - "}") + """ + import java.sql.Time; + import java.time.Instant; + public class TestClass { + public void badApis(Time time) { + // BUG: Diagnostic contains: toLocalTime() + Instant instant = time.toInstant(); + } + } + """) .doTest(); } @@ -407,19 +448,21 @@ public void javaSqlTime_dateGetters() { testHelper .addSourceLines( "TestClass.java", - "import java.sql.Time;", - "public class TestClass {", - " public void badApis(Time time) {", - " // BUG: Diagnostic contains: DoNotCall", - " int year = time.getYear();", - " // BUG: Diagnostic contains: DoNotCall", - " int month = time.getMonth();", - " // BUG: Diagnostic contains: DoNotCall", - " int day = time.getDay();", - " // BUG: Diagnostic contains: DoNotCall", - " int date = time.getDate();", - " }", - "}") + """ + import java.sql.Time; + public class TestClass { + public void badApis(Time time) { + // BUG: Diagnostic contains: DoNotCall + int year = time.getYear(); + // BUG: Diagnostic contains: DoNotCall + int month = time.getMonth(); + // BUG: Diagnostic contains: DoNotCall + int day = time.getDay(); + // BUG: Diagnostic contains: DoNotCall + int date = time.getDate(); + } + } + """) .doTest(); } @@ -432,17 +475,19 @@ public void javaSqlTime_dateSetters() { testHelper .addSourceLines( "TestClass.java", - "import java.sql.Time;", - "public class TestClass {", - " public void badApis(Time time) {", - " // BUG: Diagnostic contains: DoNotCall", - " time.setYear(1);", - " // BUG: Diagnostic contains: DoNotCall", - " time.setMonth(1);", - " // BUG: Diagnostic contains: DoNotCall", - " time.setDate(1);", - " }", - "}") + """ + import java.sql.Time; + public class TestClass { + public void badApis(Time time) { + // BUG: Diagnostic contains: DoNotCall + time.setYear(1); + // BUG: Diagnostic contains: DoNotCall + time.setMonth(1); + // BUG: Diagnostic contains: DoNotCall + time.setDate(1); + } + } + """) .doTest(); } @@ -451,21 +496,23 @@ public void javaSqlTime_staticallyTypedAsJavaUtilDate() { testHelper .addSourceLines( "TestClass.java", - "import java.time.Instant;", - "import java.util.Date;", - "public class TestClass {", - " public void badApis() {", - " Date time = new java.sql.Time(1234567890L);", - " Instant instant = time.toInstant();", - " int year = time.getYear();", - " int month = time.getMonth();", - " int date = time.getDate();", - " int day = time.getDay();", - " time.setYear(1);", - " time.setMonth(1);", - " time.setDate(1);", - " }", - "}") + """ + import java.time.Instant; + import java.util.Date; + public class TestClass { + public void badApis() { + Date time = new java.sql.Time(1234567890L); + Instant instant = time.toInstant(); + int year = time.getYear(); + int month = time.getMonth(); + int date = time.getDate(); + int day = time.getDay(); + time.setYear(1); + time.setMonth(1); + time.setDate(1); + } + } + """) .doTest(); } @@ -477,14 +524,16 @@ public void readLock_newCondition() { testHelper .addSourceLines( "Test.java", - "import java.util.concurrent.locks.ReentrantReadWriteLock;", - "public class Test {", - " public void foo() {", - " ReentrantReadWriteLock.ReadLock lock = new ReentrantReadWriteLock().readLock();", - " // BUG: Diagnostic contains: DoNotCall", - " lock.newCondition();", - " }", - "}") + """ + import java.util.concurrent.locks.ReentrantReadWriteLock; + public class Test { + public void foo() { + ReentrantReadWriteLock.ReadLock lock = new ReentrantReadWriteLock().readLock(); + // BUG: Diagnostic contains: DoNotCall + lock.newCondition(); + } + } + """) .doTest(); } @@ -495,14 +544,16 @@ public void threadLocalRandom_setSeed() { testHelper .addSourceLines( "Test.java", - "import java.util.concurrent.ThreadLocalRandom;", - "public class Test {", - " public void foo() {", - " ThreadLocalRandom random = ThreadLocalRandom.current();", - " // BUG: Diagnostic contains: DoNotCall", - " random.setSeed(42L);", - " }", - "}") + """ + import java.util.concurrent.ThreadLocalRandom; + public class Test { + public void foo() { + ThreadLocalRandom random = ThreadLocalRandom.current(); + // BUG: Diagnostic contains: DoNotCall + random.setSeed(42L); + } + } + """) .doTest(); } @@ -511,15 +562,17 @@ public void memberReferencesOnThirdPartyMethods() { testHelper .addSourceLines( "Test.java", - "import java.util.concurrent.ThreadLocalRandom;", - "import java.util.Optional;", - "public class Test {", - " public void foo(Optional x) {", - " ThreadLocalRandom random = ThreadLocalRandom.current();", - " // BUG: Diagnostic contains: DoNotCall", - " x.ifPresent(random::setSeed);", - " }", - "}") + """ + import java.util.concurrent.ThreadLocalRandom; + import java.util.Optional; + public class Test { + public void foo(Optional x) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + // BUG: Diagnostic contains: DoNotCall + x.ifPresent(random::setSeed); + } + } + """) .doTest(); } @@ -528,13 +581,15 @@ public void typeArgs_dontCrash() { testHelper .addSourceLines( "Test.java", - "import java.util.List;", - "class Test> {", - " @Override public boolean equals(Object o) {", - " T foo = (T) o;", - " return foo.equals(1);", - " }", - "}") + """ + import java.util.List; + class Test> { + @Override public boolean equals(Object o) { + T foo = (T) o; + return foo.equals(1); + } + } + """) .doTest(); } @@ -543,16 +598,18 @@ public void positive_getSimpleName_refactoredToGetClassName() { testHelper .addSourceLines( "Test.java", - "class Test{", - " void f() {", - " try {", - " throw new Exception();", - " } catch (Exception ex) {", - " // BUG: Diagnostic contains: getClassName", - " ex.getStackTrace()[0].getClass().getSimpleName();", - " }", - " }", - "}") + """ + class Test{ + void f() { + try { + throw new Exception(); + } catch (Exception ex) { + // BUG: Diagnostic contains: getClassName + ex.getStackTrace()[0].getClass().getSimpleName(); + } + } + } + """) .doTest(); } @@ -561,12 +618,14 @@ public void positive_stackWalkerGetClass() { testHelper .addSourceLines( "Test.java", - "class Test{", - " void f(StackWalker w) {", - " // BUG: Diagnostic contains: getCallerClass", - " w.getClass();", - " }", - "}") + """ + class Test{ + void f(StackWalker w) { + // BUG: Diagnostic contains: getCallerClass + w.getClass(); + } + } + """) .doTest(); } @@ -575,13 +634,15 @@ public void positive_stackFrameGetClass() { testHelper .addSourceLines( "Test.java", - "import java.lang.StackWalker.StackFrame;", - "class Test{", - " void f(StackFrame f) {", - " // BUG: Diagnostic contains: getClassName", - " f.getClass();", - " }", - "}") + """ + import java.lang.StackWalker.StackFrame; + class Test{ + void f(StackFrame f) { + // BUG: Diagnostic contains: getClassName + f.getClass(); + } + } + """) .doTest(); } @@ -590,13 +651,15 @@ public void positive_constructorGetClass() { testHelper .addSourceLines( "Test.java", - "import java.lang.reflect.Constructor;", - "class Test{", - " void f(Constructor c) {", - " // BUG: Diagnostic contains: getDeclaringClass", - " c.getClass();", - " }", - "}") + """ + import java.lang.reflect.Constructor; + class Test{ + void f(Constructor c) { + // BUG: Diagnostic contains: getDeclaringClass + c.getClass(); + } + } + """) .doTest(); } @@ -605,13 +668,15 @@ public void positive_fieldGetClass() { testHelper .addSourceLines( "Test.java", - "import java.lang.reflect.Field;", - "class Test{", - " void f(Field f) {", - " // BUG: Diagnostic contains: getDeclaringClass", - " f.getClass();", - " }", - "}") + """ + import java.lang.reflect.Field; + class Test{ + void f(Field f) { + // BUG: Diagnostic contains: getDeclaringClass + f.getClass(); + } + } + """) .doTest(); } @@ -620,13 +685,15 @@ public void positive_methodGetClass() { testHelper .addSourceLines( "Test.java", - "import java.lang.reflect.Method;", - "class Test{", - " void f(Method m) {", - " // BUG: Diagnostic contains: getDeclaringClass", - " m.getClass();", - " }", - "}") + """ + import java.lang.reflect.Method; + class Test{ + void f(Method m) { + // BUG: Diagnostic contains: getDeclaringClass + m.getClass(); + } + } + """) .doTest(); } @@ -635,13 +702,15 @@ public void positive_beanDescriptorGetClass() { testHelper .addSourceLines( "Test.java", - "import java.beans.BeanDescriptor;", - "class Test{", - " void f(BeanDescriptor b) {", - " // BUG: Diagnostic contains: getBeanClass", - " b.getClass();", - " }", - "}") + """ + import java.beans.BeanDescriptor; + class Test{ + void f(BeanDescriptor b) { + // BUG: Diagnostic contains: getBeanClass + b.getClass(); + } + } + """) .doTest(); } @@ -650,16 +719,18 @@ public void positive_lockInfoGetClass() { testHelper .addSourceLines( "Test.java", - "import java.lang.management.LockInfo;", - "import java.lang.management.MonitorInfo;", - "class Test{", - " void f(LockInfo l, MonitorInfo m) {", - " // BUG: Diagnostic contains: getClassName", - " l.getClass();", - " // BUG: Diagnostic contains: getClassName", - " m.getClass();", - " }", - "}") + """ + import java.lang.management.LockInfo; + import java.lang.management.MonitorInfo; + class Test{ + void f(LockInfo l, MonitorInfo m) { + // BUG: Diagnostic contains: getClassName + l.getClass(); + // BUG: Diagnostic contains: getClassName + m.getClass(); + } + } + """) .doTest(); } @@ -668,13 +739,15 @@ public void positive_parameterizedTypeGetClass() { testHelper .addSourceLines( "Test.java", - "import java.lang.reflect.ParameterizedType;", - "class Test{", - " void f(ParameterizedType t) {", - " // BUG: Diagnostic contains: getRawType", - " t.getClass();", - " }", - "}") + """ + import java.lang.reflect.ParameterizedType; + class Test{ + void f(ParameterizedType t) { + // BUG: Diagnostic contains: getRawType + t.getClass(); + } + } + """) .doTest(); } @@ -683,13 +756,15 @@ public void positive_classInfoGetClass() { testHelper .addSourceLines( "Test.java", - "import com.google.common.reflect.ClassPath.ClassInfo;", - "class Test{", - " void f(ClassInfo i) {", - " // BUG: Diagnostic contains: getName", - " i.getClass();", - " }", - "}") + """ + import com.google.common.reflect.ClassPath.ClassInfo; + class Test{ + void f(ClassInfo i) { + // BUG: Diagnostic contains: getName + i.getClass(); + } + } + """) .doTest(); } @@ -698,13 +773,15 @@ public void positive_typeTokenGetClass() { testHelper .addSourceLines( "Test.java", - "import com.google.common.reflect.TypeToken;", - "class Test{", - " void f(TypeToken t) {", - " // BUG: Diagnostic contains: getRawType", - " t.getClass();", - " }", - "}") + """ + import com.google.common.reflect.TypeToken; + class Test{ + void f(TypeToken t) { + // BUG: Diagnostic contains: getRawType + t.getClass(); + } + } + """) .doTest(); } @@ -713,12 +790,14 @@ public void positive_threadRun() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void f(Thread t) {", - " // BUG: Diagnostic contains: start", - " t.run();", - " }", - "}") + """ + class Test { + void f(Thread t) { + // BUG: Diagnostic contains: start + t.run(); + } + } + """) .doTest(); } @@ -727,11 +806,13 @@ public void negative_threadSuperRun() { testHelper .addSourceLines( "Test.java", - "class Test extends Thread {", - " @Override public void run() {", - " super.run();", - " }", - "}") + """ + class Test extends Thread { + @Override public void run() { + super.run(); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/DuplicateMapKeysTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/DuplicateMapKeysTest.java index 25eff8ae220..e50146d5f85 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/DuplicateMapKeysTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/DuplicateMapKeysTest.java @@ -37,19 +37,21 @@ public void positiveCase() { compilationHelper .addSourceLines( "a/A.java", - "package a;", - "import static java.util.Map.entry;", - "import java.util.Map;", - "class A {", - " public static void test() {", - " // BUG: Diagnostic contains: Foo", - " Map map = Map.ofEntries(", - " entry(\"Foo\", \"Bar\"),", - " entry(\"Ping\", \"Pong\"),", - " entry(\"Kit\", \"Kat\"),", - " entry(\"Foo\", \"Bar\"));", - " }", - "}") + """ + package a; + import static java.util.Map.entry; + import java.util.Map; + class A { + public static void test() { + // BUG: Diagnostic contains: Foo + Map map = Map.ofEntries( + entry("Foo", "Bar"), + entry("Ping", "Pong"), + entry("Kit", "Kat"), + entry("Foo", "Bar")); + } + } + """) .doTest(); } @@ -58,18 +60,20 @@ public void negativeCase() { compilationHelper .addSourceLines( "a/A.java", - "package a;", - "import static java.util.Map.entry;", - "import java.util.Map;", - "class A {", - " public static void test() {", - " Map map = Map.ofEntries(", - " entry(\"Foo\", \"Bar\"),", - " entry(\"Ping\", \"Pong\"),", - " entry(\"Kit\", \"Kat\"),", - " entry(\"Food\", \"Bar\"));", - " }", - "}") + """ + package a; + import static java.util.Map.entry; + import java.util.Map; + class A { + public static void test() { + Map map = Map.ofEntries( + entry("Foo", "Bar"), + entry("Ping", "Pong"), + entry("Kit", "Kat"), + entry("Food", "Bar")); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/EmptyTopLevelDeclarationTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/EmptyTopLevelDeclarationTest.java index d69211cca73..fe057bf80c2 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/EmptyTopLevelDeclarationTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/EmptyTopLevelDeclarationTest.java @@ -30,7 +30,14 @@ public class EmptyTopLevelDeclarationTest { @Test public void negative() { - compilationHelper.addSourceLines("a/A.java", "package a;", "class One {}").doTest(); + compilationHelper + .addSourceLines( + "a/A.java", + """ + package a; + class One {} + """) + .doTest(); } @Test @@ -38,9 +45,11 @@ public void positive() { compilationHelper .addSourceLines( "a/A.java", - "package a;", - "// BUG: Diagnostic contains: Did you mean 'class One {}'?", - "class One {};") + """ + package a; + // BUG: Diagnostic contains: Did you mean 'class One {}'? + class One {}; + """) .doTest(); } @@ -49,11 +58,13 @@ public void positive() { public void noImports() { compilationHelper .addSourceLines( - "ReproFile.java", // - "package errorpronecrash;", - "// BUG: Diagnostic contains: Did you mean to remove this line?", - ";", - "public class ReproFile {}") + "ReproFile.java", + """ + package errorpronecrash; + // BUG: Diagnostic contains: Did you mean to remove this line? + ; + public class ReproFile {} + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsGetClassTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsGetClassTest.java index 8b3f716c894..6eb6a3f4a6d 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsGetClassTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsGetClassTest.java @@ -40,20 +40,24 @@ public void fixes_inline() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " return o != null && o.getClass().equals(getClass()) && a == ((Test) o).a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + return o != null && o.getClass().equals(getClass()) && a == ((Test) o).a; + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " return o instanceof Test && a == ((Test) o).a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + return o instanceof Test && a == ((Test) o).a; + } + } + """) .doTest(); } @@ -62,20 +66,24 @@ public void fixes_extraParens() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " return (o != null) && (o.getClass() == getClass()) && a == ((Test) o).a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + return (o != null) && (o.getClass() == getClass()) && a == ((Test) o).a; + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " return (o instanceof Test) && a == ((Test) o).a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + return (o instanceof Test) && a == ((Test) o).a; + } + } + """) .doTest(); } @@ -84,23 +92,27 @@ public void separateNullCheck() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " if (o == null) { return false; }", - " if (o.getClass() != getClass()) { return false; }", - " return ((Test) o).a == a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + if (o == null) { return false; } + if (o.getClass() != getClass()) { return false; } + return ((Test) o).a == a; + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " if (!(o instanceof Test)) { return false; }", - " return ((Test) o).a == a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + if (!(o instanceof Test)) { return false; } + return ((Test) o).a == a; + } + } + """) .doTest(); } @@ -109,26 +121,30 @@ public void separateNullCheck_withElse() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " if (o == null) {", - " return false;", - " } else {", - " if (o.getClass() != getClass()) { return false; }", - " return ((Test) o).a == a;", - " }", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + if (o == null) { + return false; + } else { + if (o.getClass() != getClass()) { return false; } + return ((Test) o).a == a; + } + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " if (!(o instanceof Test)) { return false; }", - " return ((Test) o).a == a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + if (!(o instanceof Test)) { return false; } + return ((Test) o).a == a; + } + } + """) .doTest(); } @@ -137,23 +153,27 @@ public void separateNullCheck_noParens() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " if (o == null)", - " return false;", - " else", - " return o.getClass() == getClass() && ((Test) o).a == a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + if (o == null) + return false; + else + return o.getClass() == getClass() && ((Test) o).a == a; + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " return o instanceof Test && ((Test) o).a == a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + return o instanceof Test && ((Test) o).a == a; + } + } + """) .doTest(); } @@ -162,24 +182,28 @@ public void unnecessaryCast() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " if (o == null || !o.getClass().equals(((Object) this).getClass())) {", - " return false;", - " }", - " return ((Test) o).a == a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + if (o == null || !o.getClass().equals(((Object) this).getClass())) { + return false; + } + return ((Test) o).a == a; + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " if (!(o instanceof Test)) { return false; }", - " return ((Test) o).a == a;", - " }", - "}") + """ + class Test { + private int a; + @Override public boolean equals(Object o) { + if (!(o instanceof Test)) { return false; } + return ((Test) o).a == a; + } + } + """) .doTest(); } @@ -188,16 +212,18 @@ public void positive_unfixable() { helper .addSourceLines( "Test.java", - "import com.google.common.base.Objects;", - "class Test {", - " private int a;", - " // BUG: Diagnostic matches: NO_FIX", - " @Override public boolean equals(Object o) {", - " if (o == null) { return false; }", - " if (!Objects.equal(o.getClass(), getClass())) { return false; }", - " return ((Test) o).a == a;", - " }", - "}") + """ + import com.google.common.base.Objects; + class Test { + private int a; + // BUG: Diagnostic matches: NO_FIX + @Override public boolean equals(Object o) { + if (o == null) { return false; } + if (!Objects.equal(o.getClass(), getClass())) { return false; } + return ((Test) o).a == a; + } + } + """) .expectErrorMessage("NO_FIX", fix -> !fix.contains("instanceof Test")) .doTest(); } @@ -207,14 +233,16 @@ public void negative_final() { helper .addSourceLines( "Test.java", - "final class Test {", - " private int a;", - " @Override public boolean equals(Object o) {", - " if (o == null) { return false; }", - " if (o.getClass() != getClass()) { return false; }", - " return ((Test) o).a == a;", - " }", - "}") + """ + final class Test { + private int a; + @Override public boolean equals(Object o) { + if (o == null) { return false; } + if (o.getClass() != getClass()) { return false; } + return ((Test) o).a == a; + } + } + """) .doTest(); } @@ -223,14 +251,16 @@ public void negative_anonymous() { helper .addSourceLines( "Test.java", - "final class Test {", - " Object foo = new Object() {", - " @Override public boolean equals(Object o) {", - " if (o == null) { return false; }", - " return o.getClass() == getClass();", - " }", - " };", - "}") + """ + final class Test { + Object foo = new Object() { + @Override public boolean equals(Object o) { + if (o == null) { return false; } + return o.getClass() == getClass(); + } + }; + } + """) .doTest(); } @@ -239,14 +269,16 @@ public void negative_notOnParameter() { helper .addSourceLines( "Test.java", - "class Test {", - " private Object a;", - " @Override public boolean equals(Object o) {", - " if (o == null) { return false; }", - " if (!(o instanceof Test)) { return false; }", - " return ((Test) o).a.getClass() == a.getClass();", - " }", - "}") + """ + class Test { + private Object a; + @Override public boolean equals(Object o) { + if (o == null) { return false; } + if (!(o instanceof Test)) { return false; } + return ((Test) o).a.getClass() == a.getClass(); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ForOverrideCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ForOverrideCheckerTest.java index 310779463d2..06d5904f249 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ForOverrideCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ForOverrideCheckerTest.java @@ -29,29 +29,33 @@ public class ForOverrideCheckerTest { CompilationTestHelper.newInstance(ForOverrideChecker.class, getClass()) .addSourceLines( "test/ExtendMe.java", - "package test;", - "import com.google.errorprone.annotations.ForOverride;", - "public class ExtendMe {", - " @ForOverride", - " protected int overrideMe() { return 1; }", - " @ForOverride", - " protected int overrideMe(int a) { return 1; }", - "", - " public final void callMe() {", - " overrideMe();", - " }", - "}"); + """ + package test; + import com.google.errorprone.annotations.ForOverride; + public class ExtendMe { + @ForOverride + protected int overrideMe() { return 1; } + @ForOverride + protected int overrideMe(int a) { return 1; } + + public final void callMe() { + overrideMe(); + } + } + """); @Test public void canApplyForOverrideToProtectedMethod() { compilationHelper .addSourceLines( "test/Test.java", - "package test;", - "import com.google.errorprone.annotations.ForOverride;", - "public class Test {", - " @ForOverride protected void myMethod() {}", - "}") + """ + package test; + import com.google.errorprone.annotations.ForOverride; + public class Test { + @ForOverride protected void myMethod() {} + } + """) .doTest(); } @@ -60,11 +64,13 @@ public void canApplyForOverrideToPackagePrivateMethod() { compilationHelper .addSourceLines( "test/Test.java", - "package test;", - "import com.google.errorprone.annotations.ForOverride;", - "public class Test {", - " @ForOverride void myMethod() {}", - "}") + """ + package test; + import com.google.errorprone.annotations.ForOverride; + public class Test { + @ForOverride void myMethod() {} + } + """) .doTest(); } @@ -73,13 +79,14 @@ public void cannotApplyForOverrideToPublicMethod() { compilationHelper .addSourceLines( "test/Test.java", - "package test;", - "import com.google.errorprone.annotations.ForOverride;", - "public class Test {", - " // BUG: Diagnostic contains: @ForOverride must have protected or package-private" - + " visibility", - " @ForOverride public void myMethod() {}", - "}") + """ +package test; +import com.google.errorprone.annotations.ForOverride; +public class Test { + // BUG: Diagnostic contains: @ForOverride must have protected or package-private visibility + @ForOverride public void myMethod() {} +} +""") .doTest(); } @@ -88,13 +95,14 @@ public void cannotApplyForOverrideToPrivateMethod() { compilationHelper .addSourceLines( "test/Test.java", - "package test;", - "import com.google.errorprone.annotations.ForOverride;", - "public class Test {", - " // BUG: Diagnostic contains: @ForOverride must have protected or package-private" - + " visibility", - " @ForOverride private void myMethod() {}", - "}") + """ +package test; +import com.google.errorprone.annotations.ForOverride; +public class Test { + // BUG: Diagnostic contains: @ForOverride must have protected or package-private visibility + @ForOverride private void myMethod() {} +} +""") .doTest(); } @@ -103,13 +111,14 @@ public void cannotApplyForOverrideToInterfaceMethod() { compilationHelper .addSourceLines( "test/Test.java", - "package test;", - "import com.google.errorprone.annotations.ForOverride;", - "public interface Test {", - " // BUG: Diagnostic contains: @ForOverride must have protected or package-private" - + " visibility", - " @ForOverride void myMethod();", - "}") + """ +package test; +import com.google.errorprone.annotations.ForOverride; +public interface Test { + // BUG: Diagnostic contains: @ForOverride must have protected or package-private visibility + @ForOverride void myMethod(); +} +""") .doTest(); } @@ -118,12 +127,14 @@ public void userCanCallAppropriateMethod() { compilationHelper .addSourceLines( "test/Test.java", - "package test;", - "public class Test extends test.ExtendMe {", - " public void googleyMethod() {", - " callMe();", - " }", - "}") + """ + package test; + public class Test extends test.ExtendMe { + public void googleyMethod() { + callMe(); + } + } + """) .doTest(); } @@ -132,14 +143,16 @@ public void userInSamePackageCannotCallMethod() { compilationHelper .addSourceLines( "test/Test.java", - "package test;", - "public class Test {", - " public void tryCall() {", - " ExtendMe extendMe = new ExtendMe();", - " // BUG: Diagnostic contains: must not be invoked", - " extendMe.overrideMe();", - " }", - "}") + """ + package test; + public class Test { + public void tryCall() { + ExtendMe extendMe = new ExtendMe(); + // BUG: Diagnostic contains: must not be invoked + extendMe.overrideMe(); + } + } + """) .doTest(); } @@ -148,13 +161,15 @@ public void userCannotCallDefault() { compilationHelper .addSourceLines( "test/Test.java", - "package test;", - "public class Test extends test.ExtendMe {", - " public void circumventer() {", - " // BUG: Diagnostic contains: must not be invoked", - " overrideMe();", - " }", - "}") + """ + package test; + public class Test extends test.ExtendMe { + public void circumventer() { + // BUG: Diagnostic contains: must not be invoked + overrideMe(); + } + } + """) .doTest(); } @@ -163,18 +178,20 @@ public void userCannotCallOverridden() { compilationHelper .addSourceLines( "test/Test.java", - "package test2;", - "public class Test extends test.ExtendMe {", - " @Override", - " protected int overrideMe() {", - " System.err.println(\"Capybaras are semi-aquatic.\");", - " return 1;", - " }", - " public void circumventer() {", - " // BUG: Diagnostic contains: must not be invoked", - " overrideMe();", - " }", - "}") + """ + package test2; + public class Test extends test.ExtendMe { + @Override + protected int overrideMe() { + System.err.println("Capybaras are semi-aquatic."); + return 1; + } + public void circumventer() { + // BUG: Diagnostic contains: must not be invoked + overrideMe(); + } + } + """) .doTest(); } @@ -183,13 +200,15 @@ public void userCanCallSuperFromOverridden() { compilationHelper .addSourceLines( "test/Test.java", - "package test2;", - "public class Test extends test.ExtendMe {", - " @Override", - " protected int overrideMe() {", - " return super.overrideMe();", - " }", - "}") + """ + package test2; + public class Test extends test.ExtendMe { + @Override + protected int overrideMe() { + return super.overrideMe(); + } + } + """) .doTest(); } @@ -214,13 +233,15 @@ public void userCannotCallSuperFromNonOverriddenMethod() { compilationHelper .addSourceLines( "test/Test.java", - "package test2;", - "public class Test extends test.ExtendMe {", - " protected void circumventer() {", - " // BUG: Diagnostic contains: must not be invoked", - " super.overrideMe();", - " }", - "}") + """ + package test2; + public class Test extends test.ExtendMe { + protected void circumventer() { + // BUG: Diagnostic contains: must not be invoked + super.overrideMe(); + } + } + """) .doTest(); } @@ -229,11 +250,13 @@ public void userCannotCallSuperFromFieldInitializer() { compilationHelper .addSourceLines( "test/Test.java", - "package test2;", - "public class Test extends test.ExtendMe {", - " // BUG: Diagnostic contains: must not be invoked", - " private final int k = super.overrideMe();", - "}") + """ + package test2; + public class Test extends test.ExtendMe { + // BUG: Diagnostic contains: must not be invoked + private final int k = super.overrideMe(); + } + """) .doTest(); } @@ -242,21 +265,23 @@ public void userCannotCallSuperFromAnonymousInnerClassInOverride() { compilationHelper .addSourceLines( "test/Test.java", - "package test2;", - "public class Test extends test.ExtendMe {", - " @Override", - " protected int overrideMe() {", - " return new Object() {", - " // BUG: Diagnostic contains: must not be invoked", - " final int k = Test.super.overrideMe();", - "", - " int foo() {", - " // BUG: Diagnostic contains: must not be invoked", - " return Test.super.overrideMe();", - " }", - " }.foo();", - " }", - "}") + """ + package test2; + public class Test extends test.ExtendMe { + @Override + protected int overrideMe() { + return new Object() { + // BUG: Diagnostic contains: must not be invoked + final int k = Test.super.overrideMe(); + + int foo() { + // BUG: Diagnostic contains: must not be invoked + return Test.super.overrideMe(); + } + }.foo(); + } + } + """) .doTest(); } @@ -265,17 +290,19 @@ public void userCannotMakeMethodPublic() { compilationHelper .addSourceLines( "test/Test.java", - "package test2;", - "public class Test extends test.ExtendMe {", - " // BUG: Diagnostic contains: overrides @ForOverride method test.ExtendMe.overrideMe", - " public int overrideMe() {", - " return 1;", - " }", - " // BUG: Diagnostic contains: overrides @ForOverride method test.ExtendMe.overrideMe", - " public int overrideMe(int a) {", - " return 1;", - " }", - "}") + """ + package test2; + public class Test extends test.ExtendMe { + // BUG: Diagnostic contains: overrides @ForOverride method test.ExtendMe.overrideMe + public int overrideMe() { + return 1; + } + // BUG: Diagnostic contains: overrides @ForOverride method test.ExtendMe.overrideMe + public int overrideMe(int a) { + return 1; + } + } + """) .doTest(); } @@ -284,17 +311,19 @@ public void definerCanCallFromInnerClass() { compilationHelper .addSourceLines( "test/OuterClass.java", - "package test;", - "import com.google.errorprone.annotations.ForOverride;", - "public class OuterClass {", - " @ForOverride", - " protected void forOverride() { }", - " private class InnerClass {", - " void invoke() {", - " forOverride();", - " }", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.ForOverride; + public class OuterClass { + @ForOverride + protected void forOverride() { } + private class InnerClass { + void invoke() { + forOverride(); + } + } + } + """) .doTest(); } @@ -303,19 +332,21 @@ public void definerCanCallFromAnonymousInnerClass() { compilationHelper .addSourceLines( "test/OuterClass.java", - "package test;", - "import com.google.errorprone.annotations.ForOverride;", - "public class OuterClass {", - " @ForOverride", - " protected void forOverride() { }", - " public Runnable getRunner() {", - " return new Runnable() {", - " public void run() {", - " forOverride();", - " }", - " };", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.ForOverride; + public class OuterClass { + @ForOverride + protected void forOverride() { } + public Runnable getRunner() { + return new Runnable() { + public void run() { + forOverride(); + } + }; + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/FunctionalInterfaceClashTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/FunctionalInterfaceClashTest.java index 12bddfcfef5..3e3c08e4e26 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/FunctionalInterfaceClashTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/FunctionalInterfaceClashTest.java @@ -35,14 +35,16 @@ public class FunctionalInterfaceClashTest { public void positive() { testHelper .addSourceLines( - "Test.java", // - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class Test {", - " // BUG: Diagnostic contains: foo(Function)", - " void foo(Consumer x) {}", - " void foo(Function c) {}", - "}") + "Test.java", + """ + import java.util.function.Function; + import java.util.function.Consumer; + public class Test { + // BUG: Diagnostic contains: foo(Function) + void foo(Consumer x) {} + void foo(Function c) {} + } + """) .doTest(); } @@ -50,16 +52,18 @@ public void positive() { public void positiveNullary() { testHelper .addSourceLines( - "Test.java", // - "import java.util.concurrent.Callable;", - "public class Test {", - " interface MyCallable {", - " String call();", - " }", - " // BUG: Diagnostic contains: foo(MyCallable)", - " void foo(Callable x) {}", - " void foo(MyCallable c) {}", - "}") + "Test.java", + """ + import java.util.concurrent.Callable; + public class Test { + interface MyCallable { + String call(); + } + // BUG: Diagnostic contains: foo(MyCallable) + void foo(Callable x) {} + void foo(MyCallable c) {} + } + """) .doTest(); } @@ -67,18 +71,22 @@ public void positiveNullary() { public void positiveInherited() { testHelper .addSourceLines( - "Super.java", // - "import java.util.function.Function;", - "class Super {", - " void foo(Function x) {}", - "}") + "Super.java", + """ + import java.util.function.Function; + class Super { + void foo(Function x) {} + } + """) .addSourceLines( - "Test.java", // - "import java.util.function.Consumer;", - "public class Test extends Super {", - " // BUG: Diagnostic contains: Super.foo(Function)", - " void foo(Consumer c) {}", - "}") + "Test.java", + """ + import java.util.function.Consumer; + public class Test extends Super { + // BUG: Diagnostic contains: Super.foo(Function) + void foo(Consumer c) {} + } + """) .doTest(); } @@ -86,14 +94,16 @@ public void positiveInherited() { public void positiveArgs() { testHelper .addSourceLines( - "Test.java", // - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class Test {", - " // BUG: Diagnostic contains: foo(Function)", - " void foo(Consumer c) {}", - " void foo(Function f) {}", - "}") + "Test.java", + """ + import java.util.function.Function; + import java.util.function.Consumer; + public class Test { + // BUG: Diagnostic contains: foo(Function) + void foo(Consumer c) {} + void foo(Function f) {} + } + """) .doTest(); } @@ -101,17 +111,21 @@ public void positiveArgs() { public void negativeOverride() { testHelper .addSourceLines( - "Super.java", // - "import java.util.function.Consumer;", - "class Super {", - " void foo(Consumer x) {}", - "}") + "Super.java", + """ + import java.util.function.Consumer; + class Super { + void foo(Consumer x) {} + } + """) .addSourceLines( - "Test.java", // - "import java.util.function.Consumer;", - "public class Test extends Super {", - " void foo(Consumer x) {}", - "}") + "Test.java", + """ + import java.util.function.Consumer; + public class Test extends Super { + void foo(Consumer x) {} + } + """) .doTest(); } @@ -119,17 +133,21 @@ public void negativeOverride() { public void negativeSuperConstructor() { testHelper .addSourceLines( - "Super.java", // - "import java.util.function.Function;", - "class Super {", - " Super(Function r) {}", - "}") + "Super.java", + """ + import java.util.function.Function; + class Super { + Super(Function r) {} + } + """) .addSourceLines( - "Test.java", // - "import java.util.function.Consumer;", - "public class Test extends Super {", - " Test(Consumer r) { super(null); }", - "}") + "Test.java", + """ + import java.util.function.Consumer; + public class Test extends Super { + Test(Consumer r) { super(null); } + } + """) .doTest(); } @@ -137,14 +155,16 @@ public void negativeSuperConstructor() { public void positiveConstructor() { testHelper .addSourceLines( - "Test.java", // - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class Test {", - " // BUG: Diagnostic contains: Test(Function)", - " Test(Consumer r) {}", - " Test(Function c) {}", - "}") + "Test.java", + """ + import java.util.function.Function; + import java.util.function.Consumer; + public class Test { + // BUG: Diagnostic contains: Test(Function) + Test(Consumer r) {} + Test(Function c) {} + } + """) .doTest(); } @@ -152,14 +172,16 @@ public void positiveConstructor() { public void positiveStatic() { testHelper .addSourceLines( - "Test.java", // - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class Test {", - " // BUG: Diagnostic contains: foo(Function)", - " static void foo(Consumer x) {}", - " void foo(Function c) {}", - "}") + "Test.java", + """ + import java.util.function.Function; + import java.util.function.Consumer; + public class Test { + // BUG: Diagnostic contains: foo(Function) + static void foo(Consumer x) {} + void foo(Function c) {} + } + """) .doTest(); } @@ -168,14 +190,16 @@ public void suppressWarningsOnMethod() { testHelper .addSourceLines( "Test.java", - "import java.lang.SuppressWarnings;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class Test {", - " @SuppressWarnings(\"FunctionalInterfaceClash\")", - " void foo(Consumer x) {}", - " void foo(Function c) {}", - "}") + """ + import java.lang.SuppressWarnings; + import java.util.function.Function; + import java.util.function.Consumer; + public class Test { + @SuppressWarnings("FunctionalInterfaceClash") + void foo(Consumer x) {} + void foo(Function c) {} + } + """) .doTest(); } @@ -184,40 +208,48 @@ public void shouldIgnore_transitiveInheritanceWithExpandedVisibility() { testHelper .addSourceLines( "pkg1/FunctionalInterface.java", - "package pkg1;", - "public interface FunctionalInterface {", - " String apply(String s);", - "}") + """ + package pkg1; + public interface FunctionalInterface { + String apply(String s); + } + """) .addSourceLines( "pkg2/BaseClass.java", - "package pkg2;", - "import pkg1.FunctionalInterface;", - "public abstract class BaseClass {", - " abstract String doIt(FunctionalInterface fi);", - "}") + """ + package pkg2; + import pkg1.FunctionalInterface; + public abstract class BaseClass { + abstract String doIt(FunctionalInterface fi); + } + """) .addSourceLines( "pkg2/DerivedClass.java", - "package pkg2;", - "import pkg1.FunctionalInterface;", - "public class DerivedClass extends BaseClass {", - " @Override public String doIt(FunctionalInterface fi) {", - " return null;", - " }", - "}") + """ + package pkg2; + import pkg1.FunctionalInterface; + public class DerivedClass extends BaseClass { + @Override public String doIt(FunctionalInterface fi) { + return null; + } + } + """) .addSourceLines( "pkg3/Test.java", - "package pkg3;", - "import pkg1.FunctionalInterface;", - "import pkg2.DerivedClass;", - "public class Test {", - " DerivedClass getDerivedClass() {", - " return new DerivedClass() {", - " @Override public String doIt(FunctionalInterface fi) {", - " return null;", - " }", - " };", - " }", - "}") + """ + package pkg3; + import pkg1.FunctionalInterface; + import pkg2.DerivedClass; + public class Test { + DerivedClass getDerivedClass() { + return new DerivedClass() { + @Override public String doIt(FunctionalInterface fi) { + return null; + } + }; + } + } + """) .doTest(); } @@ -226,23 +258,27 @@ public void negative_multipleClashingOverriddenMethods() { testHelper .addSourceLines( "pkg2/BaseClass.java", - "package pkg2;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public abstract class BaseClass {", - " // BUG: Diagnostic contains: When passing lambda arguments to this function", - " abstract void baz(Consumer c);", - " abstract void baz(Function f);", - "}") + """ + package pkg2; + import java.util.function.Function; + import java.util.function.Consumer; + public abstract class BaseClass { + // BUG: Diagnostic contains: When passing lambda arguments to this function + abstract void baz(Consumer c); + abstract void baz(Function f); + } + """) .addSourceLines( "pkg2/DerivedClass.java", - "package pkg2;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class DerivedClass extends BaseClass {", - " @Override void baz(Consumer c) {}", - " @Override void baz(Function f) {}", - "}") + """ + package pkg2; + import java.util.function.Function; + import java.util.function.Consumer; + public class DerivedClass extends BaseClass { + @Override void baz(Consumer c) {} + @Override void baz(Function f) {} + } + """) .doTest(); } @@ -251,20 +287,24 @@ public void negative_singleClashingOverriddenMethods() { testHelper .addSourceLines( "pkg2/BaseClass.java", - "package pkg2;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public abstract class BaseClass {", - " abstract void bar(Consumer c);", - "}") + """ + package pkg2; + import java.util.function.Function; + import java.util.function.Consumer; + public abstract class BaseClass { + abstract void bar(Consumer c); + } + """) .addSourceLines( "pkg2/DerivedClass.java", - "package pkg2;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class DerivedClass extends BaseClass {", - " @Override void bar(Consumer c) {}", - "}") + """ + package pkg2; + import java.util.function.Function; + import java.util.function.Consumer; + public class DerivedClass extends BaseClass { + @Override void bar(Consumer c) {} + } + """) .doTest(); } @@ -273,22 +313,26 @@ public void positive_overriddenAndNewClashingMethod() { testHelper .addSourceLines( "pkg2/BaseClass.java", - "package pkg2;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class BaseClass {", - " void conduct(Consumer c) {}", - "}") + """ + package pkg2; + import java.util.function.Function; + import java.util.function.Consumer; + public class BaseClass { + void conduct(Consumer c) {} + } + """) .addSourceLines( "pkg2/ConductClass.java", - "package pkg2;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class ConductClass extends BaseClass {", - " // BUG: Diagnostic contains: disambiguate with:", - " @Override void conduct(Consumer c) {}", - " void conduct(Function f) {}", - "}") + """ + package pkg2; + import java.util.function.Function; + import java.util.function.Consumer; + public class ConductClass extends BaseClass { + // BUG: Diagnostic contains: disambiguate with: + @Override void conduct(Consumer c) {} + void conduct(Function f) {} + } + """) .doTest(); } @@ -297,20 +341,24 @@ public void negative_overriddenMethod() { testHelper .addSourceLines( "pkg2/BaseClass.java", - "package pkg2;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class BaseClass {", - " void conduct(Consumer c) {}", - "}") + """ + package pkg2; + import java.util.function.Function; + import java.util.function.Consumer; + public class BaseClass { + void conduct(Consumer c) {} + } + """) .addSourceLines( "pkg2/ConductClass.java", - "package pkg2;", - "import java.util.function.Function;", - "import java.util.function.Consumer;", - "public class ConductClass extends BaseClass {", - " @Override void conduct(Consumer c) {}", - "}") + """ + package pkg2; + import java.util.function.Function; + import java.util.function.Consumer; + public class ConductClass extends BaseClass { + @Override void conduct(Consumer c) {} + } + """) .doTest(); } @@ -319,26 +367,32 @@ public void positive_overriddenInClassAndNewClashingMethod() { testHelper .addSourceLines( "pkg2/Super.java", - "package pkg2;", - "import java.util.function.Consumer;", - "public abstract class Super {", - " void barr(Consumer c) {}", - "}") + """ + package pkg2; + import java.util.function.Consumer; + public abstract class Super { + void barr(Consumer c) {} + } + """) .addSourceLines( "pkg2/BaseClass.java", - "package pkg2;", - "import java.util.function.Consumer;", - "public abstract class BaseClass extends Super {", - " void barr(Consumer c) {}", - "}") + """ + package pkg2; + import java.util.function.Consumer; + public abstract class BaseClass extends Super { + void barr(Consumer c) {} + } + """) .addSourceLines( "pkg2/MyDerivedClass.java", - "package pkg2;", - "import java.util.function.Function;", - "public class MyDerivedClass extends BaseClass {", - " // BUG: Diagnostic contains: disambiguate with:", - " void barr(Function f) {}", - "}") + """ + package pkg2; + import java.util.function.Function; + public class MyDerivedClass extends BaseClass { + // BUG: Diagnostic contains: disambiguate with: + void barr(Function f) {} + } + """) .doTest(); } @@ -347,26 +401,30 @@ public void positive_overridesInClassAndNewClashingPairInSameClass() { testHelper .addSourceLines( "pkg2/Super.java", - "package pkg2;", - "import java.util.function.Consumer;", - "import java.util.function.Function;", - "public abstract class Super {", - " // BUG: Diagnostic contains: When passing lambda arguments to this function", - " void barr(Function f) {}", - " void barr(Consumer c) {}", - "}") + """ + package pkg2; + import java.util.function.Consumer; + import java.util.function.Function; + public abstract class Super { + // BUG: Diagnostic contains: When passing lambda arguments to this function + void barr(Function f) {} + void barr(Consumer c) {} + } + """) .addSourceLines( "pkg2/BaseClass.java", - "package pkg2;", - "import java.util.function.Consumer;", - "import java.util.function.Function;", - "public abstract class BaseClass extends Super {", - " void barr(Function f) {}", - " void barr(Consumer c) {}", - " // BUG: Diagnostic contains: When passing lambda arguments to this function", - " void foo(Function f) {}", - " void foo(Consumer c) {}", - "}") + """ + package pkg2; + import java.util.function.Consumer; + import java.util.function.Function; + public abstract class BaseClass extends Super { + void barr(Function f) {} + void barr(Consumer c) {} + // BUG: Diagnostic contains: When passing lambda arguments to this function + void foo(Function f) {} + void foo(Consumer c) {} + } + """) .doTest(); } @@ -375,12 +433,14 @@ public void oneIsMoreSpecific_notAmbiguous() { testHelper .addSourceLines( "Test.java", - "import java.util.function.Consumer;", - "public class Test {", - " void foo(Consumer c) {}", - " void foo(SubConsumer c) {}", - " interface SubConsumer extends Consumer {}", - "}") + """ + import java.util.function.Consumer; + public class Test { + void foo(Consumer c) {} + void foo(SubConsumer c) {} + interface SubConsumer extends Consumer {} + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/InconsistentHashCodeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/InconsistentHashCodeTest.java index 1e1fa7dbcd1..b8d09a7e5e4 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/InconsistentHashCodeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/InconsistentHashCodeTest.java @@ -36,17 +36,19 @@ public void negative() { helper .addSourceLines( "Test.java", - "class Test {", - " private int a;", - " private int b;", - " @Override public boolean equals(Object o) {", - " Test that = (Test) o;", - " return a == that.a && b == that.b;", - " }", - " @Override public int hashCode() {", - " return a + 31 * b;", - " }", - "}") + """ + class Test { + private int a; + private int b; + @Override public boolean equals(Object o) { + Test that = (Test) o; + return a == that.a && b == that.b; + } + @Override public int hashCode() { + return a + 31 * b; + } + } + """) .doTest(); } @@ -55,18 +57,20 @@ public void positive() { helper .addSourceLines( "Test.java", - "class Test {", - " private int foo;", - " private int bar;", - " @Override public boolean equals(Object o) {", - " Test that = (Test) o;", - " return foo == that.foo;", - " }", - " // BUG: Diagnostic contains: bar", - " @Override public int hashCode() {", - " return foo + 31 * bar;", - " }", - "}") + """ + class Test { + private int foo; + private int bar; + @Override public boolean equals(Object o) { + Test that = (Test) o; + return foo == that.foo; + } + // BUG: Diagnostic contains: bar + @Override public int hashCode() { + return foo + 31 * bar; + } + } + """) .doTest(); } @@ -75,19 +79,21 @@ public void positiveViaGetter() { helper .addSourceLines( "Test.java", - "class Test {", - " private int foo;", - " private int bar;", - " @Override public boolean equals(Object o) {", - " Test that = (Test) o;", - " return foo == that.foo;", - " }", - " // BUG: Diagnostic contains: bar", - " @Override public int hashCode() {", - " return foo + 31 * getBar();", - " }", - " private int getBar() { return bar; }", - "}") + """ + class Test { + private int foo; + private int bar; + @Override public boolean equals(Object o) { + Test that = (Test) o; + return foo == that.foo; + } + // BUG: Diagnostic contains: bar + @Override public int hashCode() { + return foo + 31 * getBar(); + } + private int getBar() { return bar; } + } + """) .doTest(); } @@ -96,16 +102,18 @@ public void instanceEquality() { helper .addSourceLines( "Test.java", - "class Test {", - " private int a;", - " private int b;", - " @Override public boolean equals(Object o) {", - " return this == o;", - " }", - " @Override public int hashCode() {", - " return a + 31 * b;", - " }", - "}") + """ + class Test { + private int a; + private int b; + @Override public boolean equals(Object o) { + return this == o; + } + @Override public int hashCode() { + return a + 31 * b; + } + } + """) .doTest(); } @@ -114,18 +122,20 @@ public void memoizedHashCode() { helper .addSourceLines( "Test.java", - "class Test {", - " private int a;", - " private int b;", - " private int hashCode;", - " @Override public boolean equals(Object o) {", - " Test that = (Test) o;", - " return this.a == that.a && this.b == that.b;", - " }", - " @Override public int hashCode() {", - " return hashCode;", - " }", - "}") + """ + class Test { + private int a; + private int b; + private int hashCode; + @Override public boolean equals(Object o) { + Test that = (Test) o; + return this.a == that.a && this.b == that.b; + } + @Override public int hashCode() { + return hashCode; + } + } + """) .doTest(); } @@ -134,25 +144,27 @@ public void breakLabeledBlock() { helper .addSourceLines( "Test.java", - "class Test {", - " private int a;", - " private int b;", - " private int hashCode;", - " public void accessesLocalWithLabeledBreak() {", - " label: {", - " switch (a) {", - " case 0: break label;", - " }", - " }", - " }", - " @Override public boolean equals(Object o) {", - " Test that = (Test) o;", - " return this.a == that.a && this.b == that.b;", - " }", - " @Override public int hashCode() {", - " return hashCode;", - " }", - "}") + """ + class Test { + private int a; + private int b; + private int hashCode; + public void accessesLocalWithLabeledBreak() { + label: { + switch (a) { + case 0: break label; + } + } + } + @Override public boolean equals(Object o) { + Test that = (Test) o; + return this.a == that.a && this.b == that.b; + } + @Override public int hashCode() { + return hashCode; + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TestsNotRunWithinEnclosedTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TestsNotRunWithinEnclosedTest.java index 8584798498d..2b4b394af42 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TestsNotRunWithinEnclosedTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TestsNotRunWithinEnclosedTest.java @@ -37,13 +37,15 @@ public void nonEnclosedRunner_testPresumedToRun() { helper .addSourceLines( "FooTest.java", - "import org.junit.Test;", - "import org.junit.runner.RunWith;", - "import org.junit.runners.JUnit4;", - "@RunWith(JUnit4.class)", - "public final class FooTest {", - " @Test public void test() {}", - "}") + """ + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + @RunWith(JUnit4.class) + public final class FooTest { + @Test public void test() {} + } + """) .doTest(); } @@ -52,14 +54,16 @@ public void enclosingRunner_doesNotRunEnclosedTests() { helper .addSourceLines( "FooTest.java", - "import org.junit.Test;", - "import org.junit.experimental.runners.Enclosed;", - "import org.junit.runner.RunWith;", - "@RunWith(Enclosed.class)", - "public final class FooTest {", - " // BUG: Diagnostic contains:", - " @Test public void test() {}", - "}") + """ + import org.junit.Test; + import org.junit.experimental.runners.Enclosed; + import org.junit.runner.RunWith; + @RunWith(Enclosed.class) + public final class FooTest { + // BUG: Diagnostic contains: + @Test public void test() {} + } + """) .doTest(); } @@ -68,23 +72,27 @@ public void refactoring_changesToUseJunitRunner() { refactoring .addInputLines( "FooTest.java", - "import org.junit.Test;", - "import org.junit.experimental.runners.Enclosed;", - "import org.junit.runner.RunWith;", - "@RunWith(Enclosed.class)", - "public final class FooTest {", - " @Test public void test() {}", - "}") + """ + import org.junit.Test; + import org.junit.experimental.runners.Enclosed; + import org.junit.runner.RunWith; + @RunWith(Enclosed.class) + public final class FooTest { + @Test public void test() {} + } + """) .addOutputLines( "FooTest.java", - "import org.junit.Test;", - "import org.junit.experimental.runners.Enclosed;", - "import org.junit.runner.RunWith;", - "import org.junit.runners.JUnit4;", - "@RunWith(JUnit4.class)", - "public final class FooTest {", - " @Test public void test() {}", - "}") + """ + import org.junit.Test; + import org.junit.experimental.runners.Enclosed; + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + @RunWith(JUnit4.class) + public final class FooTest { + @Test public void test() {} + } + """) .doTest(); } @@ -93,14 +101,16 @@ public void enclosingRunner_butWithClassExtended_doesRunTests() { helper .addSourceLines( "FooTest.java", - "import org.junit.experimental.runners.Enclosed;", - "import org.junit.Test;", - "import org.junit.runner.RunWith;", - "@RunWith(Enclosed.class)", - "public class FooTest {", - " @Test public void test() {}", - " public class FooInnerTest extends FooTest {}", - "}") + """ + import org.junit.experimental.runners.Enclosed; + import org.junit.Test; + import org.junit.runner.RunWith; + @RunWith(Enclosed.class) + public class FooTest { + @Test public void test() {} + public class FooInnerTest extends FooTest {} + } + """) .doTest(); } @@ -109,15 +119,17 @@ public void enclosingRunner_withInnerClasses_runsTests() { helper .addSourceLines( "FooTest.java", - "import org.junit.experimental.runners.Enclosed;", - "import org.junit.Test;", - "import org.junit.runner.RunWith;", - "@RunWith(Enclosed.class)", - "public class FooTest {", - " public static class BarTest {", - " @Test public void test() {}", - " }", - "}") + """ + import org.junit.experimental.runners.Enclosed; + import org.junit.Test; + import org.junit.runner.RunWith; + @RunWith(Enclosed.class) + public class FooTest { + public static class BarTest { + @Test public void test() {} + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/MissingSuperCallTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/MissingSuperCallTest.java index 49e12063046..d96ddf25a90 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/MissingSuperCallTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/MissingSuperCallTest.java @@ -28,29 +28,35 @@ public class MissingSuperCallTest { CompilationTestHelper.newInstance(MissingSuperCall.class, getClass()) .addSourceLines( "android/support/annotation/CallSuper.java", - "package android.support.annotation;", - "import static java.lang.annotation.ElementType.METHOD;", - "import java.lang.annotation.Target;", - "@Target({METHOD})", - "public @interface CallSuper {}"); + """ + package android.support.annotation; + import static java.lang.annotation.ElementType.METHOD; + import java.lang.annotation.Target; + @Target({METHOD}) + public @interface CallSuper {} + """); @Test public void android() { compilationHelper .addSourceLines( "Super.java", - "import android.support.annotation.CallSuper;", - "public class Super {", - " @CallSuper public void doIt() {}", - "}") + """ + import android.support.annotation.CallSuper; + public class Super { + @CallSuper public void doIt() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with @CallSuper,", - " // but does not call the super method", - " @Override public void doIt() {}", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with @CallSuper, + // but does not call the super method + @Override public void doIt() {} + } + """) .doTest(); } @@ -59,22 +65,28 @@ public void androidx() { compilationHelper .addSourceLines( "androidx/annotation/CallSuper.java", - "package androidx.annotation;", - "public @interface CallSuper {}") + """ + package androidx.annotation; + public @interface CallSuper {} + """) .addSourceLines( "Super.java", - "import androidx.annotation.CallSuper;", - "public class Super {", - " @CallSuper public void doIt() {}", - "}") + """ + import androidx.annotation.CallSuper; + public class Super { + @CallSuper public void doIt() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with @CallSuper,", - " // but does not call the super method", - " @Override public void doIt() {}", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with @CallSuper, + // but does not call the super method + @Override public void doIt() {} + } + """) .doTest(); } @@ -83,18 +95,22 @@ public void javax() { compilationHelper .addSourceLines( "Super.java", - "import javax.annotation.OverridingMethodsMustInvokeSuper;", - "public class Super {", - " @OverridingMethodsMustInvokeSuper public void doIt() {}", - "}") + """ + import javax.annotation.OverridingMethodsMustInvokeSuper; + public class Super { + @OverridingMethodsMustInvokeSuper public void doIt() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with", - " // @OverridingMethodsMustInvokeSuper, but does not call the super method", - " @Override public void doIt() {}", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with + // @OverridingMethodsMustInvokeSuper, but does not call the super method + @Override public void doIt() {} + } + """) .doTest(); } @@ -103,18 +119,22 @@ public void errorProne() { compilationHelper .addSourceLines( "Super.java", - "import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper;", - "public class Super {", - " @OverridingMethodsMustInvokeSuper public void doIt() {}", - "}") + """ + import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper; + public class Super { + @OverridingMethodsMustInvokeSuper public void doIt() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with", - " // @OverridingMethodsMustInvokeSuper, but does not call the super method", - " @Override public void doIt() {}", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with + // @OverridingMethodsMustInvokeSuper, but does not call the super method + @Override public void doIt() {} + } + """) .doTest(); } @@ -123,22 +143,28 @@ public void findBugs() { compilationHelper .addSourceLines( "edu/umd/cs/findbugs/annotations/OverrideMustInvoke.java", - "package edu.umd.cs.findbugs.annotations;", - "public @interface OverrideMustInvoke {}") + """ + package edu.umd.cs.findbugs.annotations; + public @interface OverrideMustInvoke {} + """) .addSourceLines( "Super.java", - "import edu.umd.cs.findbugs.annotations.OverrideMustInvoke;", - "public class Super {", - " @OverrideMustInvoke public void doIt() {}", - "}") + """ + import edu.umd.cs.findbugs.annotations.OverrideMustInvoke; + public class Super { + @OverrideMustInvoke public void doIt() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with @OverrideMustInvoke,", - " // but does not call the super method", - " @Override public void doIt() {}", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with @OverrideMustInvoke, + // but does not call the super method + @Override public void doIt() {} + } + """) .doTest(); } @@ -147,17 +173,21 @@ public void negativeDoesCallSuper() { compilationHelper .addSourceLines( "Super.java", - "import android.support.annotation.CallSuper;", - "public class Super {", - " @CallSuper public void doIt() {}", - "}") + """ + import android.support.annotation.CallSuper; + public class Super { + @CallSuper public void doIt() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " @Override public void doIt() {", - " super.doIt();", - " }", - "}") + """ + public class Sub extends Super { + @Override public void doIt() { + super.doIt(); + } + } + """) .doTest(); } @@ -166,20 +196,24 @@ public void negativeDoesCallSuper2() { compilationHelper .addSourceLines( "Super.java", - "import android.support.annotation.CallSuper;", - "public class Super {", - " @CallSuper public Object doIt() {", - " return null;", - " }", - "}") + """ + import android.support.annotation.CallSuper; + public class Super { + @CallSuper public Object doIt() { + return null; + } + } + """) .addSourceLines( "Sub.java", - "import java.util.Objects;", - "public class Sub extends Super {", - " @Override public Object doIt() {", - " return Objects.requireNonNull(super.doIt());", - " }", - "}") + """ + import java.util.Objects; + public class Sub extends Super { + @Override public Object doIt() { + return Objects.requireNonNull(super.doIt()); + } + } + """) .doTest(); } @@ -188,18 +222,22 @@ public void negativeDoesCallInterfaceSuper() { compilationHelper .addSourceLines( "Super.java", - "import android.support.annotation.CallSuper;", - "public interface Super {", - " @CallSuper default void doIt() {}", - "}") + """ + import android.support.annotation.CallSuper; + public interface Super { + @CallSuper default void doIt() {} + } + """) .addSourceLines( "Sub.java", - "import java.util.Objects;", - "public class Sub implements Super {", - " @Override public void doIt() {", - " Super.super.doIt();", - " }", - "}") + """ + import java.util.Objects; + public class Sub implements Super { + @Override public void doIt() { + Super.super.doIt(); + } + } + """) .doTest(); } @@ -208,23 +246,29 @@ public void positiveTwoLevelsApart() { compilationHelper .addSourceLines( "a/b/c/SuperSuper.java", - "package a.b.c;", - "import javax.annotation.OverridingMethodsMustInvokeSuper;", - "public class SuperSuper {", - " @OverridingMethodsMustInvokeSuper public void doIt() {}", - "}") + """ + package a.b.c; + import javax.annotation.OverridingMethodsMustInvokeSuper; + public class SuperSuper { + @OverridingMethodsMustInvokeSuper public void doIt() {} + } + """) .addSourceLines( - "Super.java", // - "import a.b.c.SuperSuper;", - "public class Super extends SuperSuper {}") + "Super.java", + """ + import a.b.c.SuperSuper; + public class Super extends SuperSuper {} + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides a.b.c.SuperSuper#doIt, which is annotated with", - " // @OverridingMethodsMustInvokeSuper, but does not call the super method", - " @Override public void doIt() {}", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides a.b.c.SuperSuper#doIt, which is annotated with + // @OverridingMethodsMustInvokeSuper, but does not call the super method + @Override public void doIt() {} + } + """) .doTest(); } @@ -233,12 +277,14 @@ public void androidAnnotationDisallowedOnAbstractMethod() { compilationHelper .addSourceLines( "AbstractClass.java", - "import android.support.annotation.CallSuper;", - "public abstract class AbstractClass {", - " // BUG: Diagnostic contains: @CallSuper cannot be applied to an abstract method", - " @CallSuper public abstract void bad();", - " @CallSuper public void ok() {}", - "}") + """ + import android.support.annotation.CallSuper; + public abstract class AbstractClass { + // BUG: Diagnostic contains: @CallSuper cannot be applied to an abstract method + @CallSuper public abstract void bad(); + @CallSuper public void ok() {} + } + """) .doTest(); } @@ -247,13 +293,15 @@ public void javaxAnnotationDisallowedOnAbstractMethod() { compilationHelper .addSourceLines( "AbstractClass.java", - "import javax.annotation.OverridingMethodsMustInvokeSuper;", - "public abstract class AbstractClass {", - " // BUG: Diagnostic contains:", - " // @OverridingMethodsMustInvokeSuper cannot be applied to an abstract method", - " @OverridingMethodsMustInvokeSuper public abstract void bad();", - " @OverridingMethodsMustInvokeSuper public void ok() {}", - "}") + """ + import javax.annotation.OverridingMethodsMustInvokeSuper; + public abstract class AbstractClass { + // BUG: Diagnostic contains: + // @OverridingMethodsMustInvokeSuper cannot be applied to an abstract method + @OverridingMethodsMustInvokeSuper public abstract void bad(); + @OverridingMethodsMustInvokeSuper public void ok() {} + } + """) .doTest(); } @@ -262,17 +310,21 @@ public void findBugsAnnotationDisallowedOnAbstractMethod() { compilationHelper .addSourceLines( "edu/umd/cs/findbugs/annotations/OverrideMustInvoke.java", - "package edu.umd.cs.findbugs.annotations;", - "public @interface OverrideMustInvoke {}") + """ + package edu.umd.cs.findbugs.annotations; + public @interface OverrideMustInvoke {} + """) .addSourceLines( "AbstractClass.java", - "import edu.umd.cs.findbugs.annotations.OverrideMustInvoke;", - "public abstract class AbstractClass {", - " // BUG: Diagnostic contains:", - " // @OverrideMustInvoke cannot be applied to an abstract method", - " @OverrideMustInvoke public abstract void bad();", - " @OverrideMustInvoke public void ok() {}", - "}") + """ + import edu.umd.cs.findbugs.annotations.OverrideMustInvoke; + public abstract class AbstractClass { + // BUG: Diagnostic contains: + // @OverrideMustInvoke cannot be applied to an abstract method + @OverrideMustInvoke public abstract void bad(); + @OverrideMustInvoke public void ok() {} + } + """) .doTest(); } @@ -281,13 +333,15 @@ public void annotationDisallowedOnInterfaceMethod() { compilationHelper .addSourceLines( "MyInterface.java", - "import javax.annotation.OverridingMethodsMustInvokeSuper;", - "interface MyInterface {", - " // BUG: Diagnostic contains:", - " // @OverridingMethodsMustInvokeSuper cannot be applied to an abstract method", - " @OverridingMethodsMustInvokeSuper void bad();", - " @OverridingMethodsMustInvokeSuper default void ok() {}", - "}") + """ + import javax.annotation.OverridingMethodsMustInvokeSuper; + interface MyInterface { + // BUG: Diagnostic contains: + // @OverridingMethodsMustInvokeSuper cannot be applied to an abstract method + @OverridingMethodsMustInvokeSuper void bad(); + @OverridingMethodsMustInvokeSuper default void ok() {} + } + """) .doTest(); } @@ -296,18 +350,22 @@ public void positiveOverridingDefaultInterfaceMethod() { compilationHelper .addSourceLines( "MyInterface.java", - "import javax.annotation.OverridingMethodsMustInvokeSuper;", - "interface MyInterface {", - " @OverridingMethodsMustInvokeSuper default void doIt() {}", - "}") + """ + import javax.annotation.OverridingMethodsMustInvokeSuper; + interface MyInterface { + @OverridingMethodsMustInvokeSuper default void doIt() {} + } + """) .addSourceLines( "MyImplementation.java", - "public class MyImplementation implements MyInterface {", - " // BUG: Diagnostic contains:", - " // This method overrides MyInterface#doIt, which is annotated with", - " // @OverridingMethodsMustInvokeSuper, but does not call the super method", - " @Override public void doIt() {}", - "}") + """ + public class MyImplementation implements MyInterface { + // BUG: Diagnostic contains: + // This method overrides MyInterface#doIt, which is annotated with + // @OverridingMethodsMustInvokeSuper, but does not call the super method + @Override public void doIt() {} + } + """) .doTest(); } @@ -316,21 +374,25 @@ public void superAndSubAnnotated() { compilationHelper .addSourceLines( "Super.java", - "import javax.annotation.OverridingMethodsMustInvokeSuper;", - "public class Super {", - " @OverridingMethodsMustInvokeSuper public void doIt() {}", - "}") + """ + import javax.annotation.OverridingMethodsMustInvokeSuper; + public class Super { + @OverridingMethodsMustInvokeSuper public void doIt() {} + } + """) .addSourceLines( "Sub.java", - "import javax.annotation.OverridingMethodsMustInvokeSuper;", - "public class Sub extends Super {", - " @OverridingMethodsMustInvokeSuper", - " @Override", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with", - " // @OverridingMethodsMustInvokeSuper, but does not call the super method", - " public void doIt() {}", - "}") + """ + import javax.annotation.OverridingMethodsMustInvokeSuper; + public class Sub extends Super { + @OverridingMethodsMustInvokeSuper + @Override + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with + // @OverridingMethodsMustInvokeSuper, but does not call the super method + public void doIt() {} + } + """) .doTest(); } @@ -339,15 +401,19 @@ public void negativeOverridingMethodIsAbstract() { compilationHelper .addSourceLines( "Super.java", - "import javax.annotation.OverridingMethodsMustInvokeSuper;", - "public class Super {", - " @OverridingMethodsMustInvokeSuper public void doIt() {}", - "}") + """ + import javax.annotation.OverridingMethodsMustInvokeSuper; + public class Super { + @OverridingMethodsMustInvokeSuper public void doIt() {} + } + """) .addSourceLines( "Sub.java", - "public abstract class Sub extends Super {", - " @Override public abstract void doIt();", - "}") + """ + public abstract class Sub extends Super { + @Override public abstract void doIt(); + } + """) .doTest(); } @@ -356,21 +422,25 @@ public void wrongSuperCall() { compilationHelper .addSourceLines( "Super.java", - "import android.support.annotation.CallSuper;", - "public class Super {", - " @CallSuper public void doIt() {}", - " public void wrongToCall() {}", - "}") + """ + import android.support.annotation.CallSuper; + public class Super { + @CallSuper public void doIt() {} + public void wrongToCall() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with @CallSuper,", - " // but does not call the super method", - " @Override public void doIt() {", - " super.wrongToCall();", - " }", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with @CallSuper, + // but does not call the super method + @Override public void doIt() { + super.wrongToCall(); + } + } + """) .doTest(); } @@ -379,25 +449,29 @@ public void nestedSuperCall() { compilationHelper .addSourceLines( "Super.java", - "import android.support.annotation.CallSuper;", - "public class Super {", - " @CallSuper public void doIt() {}", - " public void wrongToCall() {}", - "}") + """ + import android.support.annotation.CallSuper; + public class Super { + @CallSuper public void doIt() {} + public void wrongToCall() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with @CallSuper,", - " // but does not call the super method", - " @Override public void doIt() {", - " new Super() {", - " @Override public void doIt() {", - " super.doIt();", - " }", - " };", - " }", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with @CallSuper, + // but does not call the super method + @Override public void doIt() { + new Super() { + @Override public void doIt() { + super.doIt(); + } + }; + } + } + """) .doTest(); } @@ -406,21 +480,25 @@ public void lambdas() { compilationHelper .addSourceLines( "Super.java", - "import android.support.annotation.CallSuper;", - "public class Super {", - " @CallSuper public void doIt() {}", - " public void wrongToCall() {}", - "}") + """ + import android.support.annotation.CallSuper; + public class Super { + @CallSuper public void doIt() {} + public void wrongToCall() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with @CallSuper,", - " // but does not call the super method", - " @Override public void doIt() {", - " Runnable r = () -> super.doIt();", - " }", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with @CallSuper, + // but does not call the super method + @Override public void doIt() { + Runnable r = () -> super.doIt(); + } + } + """) .doTest(); } @@ -429,21 +507,25 @@ public void methodReferences() { compilationHelper .addSourceLines( "Super.java", - "import android.support.annotation.CallSuper;", - "public class Super {", - " @CallSuper public void doIt() {}", - " public void wrongToCall() {}", - "}") + """ + import android.support.annotation.CallSuper; + public class Super { + @CallSuper public void doIt() {} + public void wrongToCall() {} + } + """) .addSourceLines( "Sub.java", - "public class Sub extends Super {", - " // BUG: Diagnostic contains:", - " // This method overrides Super#doIt, which is annotated with @CallSuper,", - " // but does not call the super method", - " @Override public void doIt() {", - " Runnable r = super::doIt;", - " }", - "}") + """ + public class Sub extends Super { + // BUG: Diagnostic contains: + // This method overrides Super#doIt, which is annotated with @CallSuper, + // but does not call the super method + @Override public void doIt() { + Runnable r = super::doIt; + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/MixedDescriptorsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/MixedDescriptorsTest.java index 8e91c1348e0..7188cf1f04d 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/MixedDescriptorsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/MixedDescriptorsTest.java @@ -36,17 +36,19 @@ public void negative() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.bugpatterns.proto.ProtoTest.TestFieldProtoMessage;", - "import com.google.errorprone.bugpatterns.proto.ProtoTest.TestProtoMessage;", - "import com.google.protobuf.Descriptors.Descriptor;", - "final class Test {", - " void test(Descriptor d) {", - " TestFieldProtoMessage.getDescriptor().findFieldByNumber(", - " TestFieldProtoMessage.FIELD_FIELD_NUMBER);", - " TestFieldProtoMessage.getDescriptor().findFieldByNumber(1);", - " d.findFieldByNumber(TestFieldProtoMessage.FIELD_FIELD_NUMBER);", - " }", - "}") + """ + import com.google.errorprone.bugpatterns.proto.ProtoTest.TestFieldProtoMessage; + import com.google.errorprone.bugpatterns.proto.ProtoTest.TestProtoMessage; + import com.google.protobuf.Descriptors.Descriptor; + final class Test { + void test(Descriptor d) { + TestFieldProtoMessage.getDescriptor().findFieldByNumber( + TestFieldProtoMessage.FIELD_FIELD_NUMBER); + TestFieldProtoMessage.getDescriptor().findFieldByNumber(1); + d.findFieldByNumber(TestFieldProtoMessage.FIELD_FIELD_NUMBER); + } + } + """) .doTest(); } @@ -55,15 +57,17 @@ public void positive() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.bugpatterns.proto.ProtoTest.TestFieldProtoMessage;", - "import com.google.errorprone.bugpatterns.proto.ProtoTest.TestProtoMessage;", - "final class Test {", - " void test() {", - " // BUG: Diagnostic contains:", - " TestFieldProtoMessage.getDescriptor().findFieldByNumber(", - " TestProtoMessage.MULTI_FIELD_FIELD_NUMBER);", - " }", - "}") + """ + import com.google.errorprone.bugpatterns.proto.ProtoTest.TestFieldProtoMessage; + import com.google.errorprone.bugpatterns.proto.ProtoTest.TestProtoMessage; + final class Test { + void test() { + // BUG: Diagnostic contains: + TestFieldProtoMessage.getDescriptor().findFieldByNumber( + TestProtoMessage.MULTI_FIELD_FIELD_NUMBER); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/NullTernaryTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/NullTernaryTest.java index 47dcb287827..d6cbf215c02 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/NullTernaryTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/NullTernaryTest.java @@ -35,26 +35,28 @@ public void positive() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void f(boolean b) {", - " // BUG: Diagnostic contains:", - " int x = b ? 0 : null;", - " // BUG: Diagnostic contains:", - " long l = b ? null : 0;", - " // BUG: Diagnostic contains:", - " g(\"\", b ? null : 0);", - " // BUG: Diagnostic contains:", - " h(\"\", 1, b ? null : 0);", - " // BUG: Diagnostic contains:", - " h(\"\", 1, b ? null : 0, 3);", - " // BUG: Diagnostic contains:", - " int z = 0 + (b ? null : 1);", - " // BUG: Diagnostic contains:", - " z = (b ? null : 1) + 0;", - " }", - " void g(String s, int y) {}", - " void h(String s, int... y) {}", - "}") + """ + class Test { + void f(boolean b) { + // BUG: Diagnostic contains: + int x = b ? 0 : null; + // BUG: Diagnostic contains: + long l = b ? null : 0; + // BUG: Diagnostic contains: + g("", b ? null : 0); + // BUG: Diagnostic contains: + h("", 1, b ? null : 0); + // BUG: Diagnostic contains: + h("", 1, b ? null : 0, 3); + // BUG: Diagnostic contains: + int z = 0 + (b ? null : 1); + // BUG: Diagnostic contains: + z = (b ? null : 1) + 0; + } + void g(String s, int y) {} + void h(String s, int... y) {} + } + """) .doTest(); } @@ -63,19 +65,21 @@ public void negative() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void f(boolean b) {", - " int x = b ? 0 : 1;", - " Integer y = b ? 0 : null;", - " g(\"\", b ? 1 : 0);", - " h(\"\", 1, b ? 1 : 0);", - " h(\"\", 1, b ? 1 : 0, 3);", - " int z = 0 + (b ? 0 : 1);", - " boolean t = (b ? 0 : null) == Integer.valueOf(0);", - " }", - " void g(String s, int y) {}", - " void h(String s, int... y) {}", - "}") + """ + class Test { + void f(boolean b) { + int x = b ? 0 : 1; + Integer y = b ? 0 : null; + g("", b ? 1 : 0); + h("", 1, b ? 1 : 0); + h("", 1, b ? 1 : 0, 3); + int z = 0 + (b ? 0 : 1); + boolean t = (b ? 0 : null) == Integer.valueOf(0); + } + void g(String s, int y) {} + void h(String s, int... y) {} + } + """) .doTest(); } @@ -84,27 +88,29 @@ public void lambdas() { testHelper .addSourceLines( "Test.java", - "class Test {", - " interface I {", - " int f();", - " }", - " interface J {", - " Integer f();", - " }", - " interface K {", - " X f();", - " }", - " void f(boolean b) {", - " // BUG: Diagnostic contains:", - " I i = () -> { return b ? null : 1; };", - " J j = () -> { return b ? null : 1; };", - " K k = () -> { return b ? null : 1; };", - " // BUG: Diagnostic contains:", - " i = () -> b ? null : 1;", - " j = () -> b ? null : 1;", - " k = () -> b ? null : 1;", - " }", - "}") + """ + class Test { + interface I { + int f(); + } + interface J { + Integer f(); + } + interface K { + X f(); + } + void f(boolean b) { + // BUG: Diagnostic contains: + I i = () -> { return b ? null : 1; }; + J j = () -> { return b ? null : 1; }; + K k = () -> { return b ? null : 1; }; + // BUG: Diagnostic contains: + i = () -> b ? null : 1; + j = () -> b ? null : 1; + k = () -> b ? null : 1; + } + } + """) .doTest(); } @@ -113,14 +119,16 @@ public void conditionalInCondition() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void conditionalInCondition(Object array, String input) {", - " int arrayDimensions = ", - " ((array!=null?input:null) == null)", - " ? 0", - " : (array!=null?input:null).length();", - " }", - "}") + """ + class Test { + void conditionalInCondition(Object array, String input) { + int arrayDimensions = + ((array!=null?input:null) == null) + ? 0 + : (array!=null?input:null).length(); + } + } + """) .doTest(); } @@ -130,18 +138,20 @@ public void expressionSwitch_doesNotCrash() { testHelper .addSourceLines( "Test.java", - "class Test {", - " static String doStuff(SomeEnum enumVar) {", - " return switch (enumVar) {", - " case A -> enumVar.name() != null ? \"AAA\" : null;", - " default -> null;", - " };", - " }", - " ", - " static enum SomeEnum {", - " A, B", - " }", - "}") + """ + class Test { + static String doStuff(SomeEnum enumVar) { + return switch (enumVar) { + case A -> enumVar.name() != null ? "AAA" : null; + default -> null; + }; + } + + static enum SomeEnum { + A, B + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ParameterNameTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ParameterNameTest.java index e727a647ede..5799b3db49f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ParameterNameTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ParameterNameTest.java @@ -38,22 +38,26 @@ public void positive() { BugCheckerRefactoringTestHelper.newInstance(ParameterName.class, getClass()) .addInputLines( "in/Test.java", - "class Test {", - " void f(int foo, int bar) {}", - " {", - " f(/* bar= */ 1, /* foo= */ 2);", - " f(/** bar= */ 3, /** foo= */ 4);", - " }", - "}") + """ + class Test { + void f(int foo, int bar) {} + { + f(/* bar= */ 1, /* foo= */ 2); + f(/** bar= */ 3, /** foo= */ 4); + } + } + """) .addOutputLines( "out/Test.java", - "class Test {", - " void f(int foo, int bar) {}", - " {", - " f(/* foo= */ 1, /* bar= */ 2);", - " f(/* foo= */ 3, /* bar= */ 4);", - " }", - "}") + """ + class Test { + void f(int foo, int bar) {} + { + f(/* foo= */ 1, /* bar= */ 2); + f(/* foo= */ 3, /* bar= */ 4); + } + } + """) .doTest(TEXT_MATCH); } @@ -62,12 +66,14 @@ public void negative() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void f(int foo, int bar) {}", - " {", - " f(/* foo= */ 1, 2);", - " }", - "}") + """ + class Test { + void f(int foo, int bar) {} + { + f(/* foo= */ 1, 2); + } + } + """) .doTest(); } @@ -76,33 +82,37 @@ public void issue781() { testHelper .addSourceLines( "a/Baz.java", - "package a.b;", - "import a.AbstractFoo;", - "class Baz extends AbstractFoo {", - " @Override", - " protected String getFoo() {", - " return \"foo\";", - " }", - "}") + """ + package a.b; + import a.AbstractFoo; + class Baz extends AbstractFoo { + @Override + protected String getFoo() { + return "foo"; + } + } + """) .addSourceLines( "a/AbstractFoo.java", - "package a;", - "import java.util.function.Function;", - "class Bar {", - " private final Function args;", - " public Bar(Function args) {", - " this.args = args;", - " }", - "}", - "public abstract class AbstractFoo {", - " protected abstract String getFoo();", - " private String getCommandArguments(String parameters) {", - " return null;", - " }", - " public AbstractFoo() {", - " new Bar(this::getCommandArguments);", - " }", - "}") + """ + package a; + import java.util.function.Function; + class Bar { + private final Function args; + public Bar(Function args) { + this.args = args; + } + } + public abstract class AbstractFoo { + protected abstract String getFoo(); + private String getCommandArguments(String parameters) { + return null; + } + public AbstractFoo() { + new Bar(this::getCommandArguments); + } + } + """) .doTest(); } @@ -111,17 +121,25 @@ public void issue792() { testHelper .addSourceLines( "a/Foo.java", - "package a;", - "class Bar {", - "}", - "public class Foo {", - " public void setInteger(Integer i) {", - " }", - " public void callSetInteger() {", - " setInteger(0);", - " }", - "}") - .addSourceLines("a/Baz.java", "package a;", "public class Baz extends Foo {", "}") + """ + package a; + class Bar { + } + public class Foo { + public void setInteger(Integer i) { + } + public void callSetInteger() { + setInteger(0); + } + } + """) + .addSourceLines( + "a/Baz.java", + """ + package a; + public class Baz extends Foo { + } + """) .doTest(); } @@ -130,12 +148,14 @@ public void namedParametersChecker_ignoresCall_withNoComments() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param1, Object param2);", - " void test(Object arg1, Object arg2) {", - " target(arg1, arg2);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param1, Object param2); + void test(Object arg1, Object arg2) { + target(arg1, arg2); + } + } + """) .doTest(); } @@ -144,13 +164,15 @@ public void namedParametersChecker_findsError_withOneBadComment() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param1, Object param2);", - " void test(Object arg1, Object arg2) {", - " // BUG: Diagnostic contains: 'target(/* param1= */arg1, arg2);'", - " target(/* param2= */arg1, arg2);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param1, Object param2); + void test(Object arg1, Object arg2) { + // BUG: Diagnostic contains: 'target(/* param1= */arg1, arg2);' + target(/* param2= */arg1, arg2); + } + } + """) .doTest(); } @@ -159,13 +181,15 @@ public void namedParametersChecker_findsError_withUnusualIdentifier() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object $param$);", - " void test(Object arg) {", - " // BUG: Diagnostic contains: 'target(/* $param$= */arg);'", - " target(/* param= */arg);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object $param$); + void test(Object arg) { + // BUG: Diagnostic contains: 'target(/* $param$= */arg);' + target(/* param= */arg); + } + } + """) .doTest(); } @@ -174,13 +198,15 @@ public void namedParametersChecker_suggestsSwap_withSwappedArgs() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param1, Object param2);", - " void test(Object arg1, Object arg2) {", - " // BUG: Diagnostic contains: 'target(/* param1= */arg2", - " target(/* param2= */arg2, /* param1= */arg1);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param1, Object param2); + void test(Object arg1, Object arg2) { + // BUG: Diagnostic contains: 'target(/* param1= */arg2 + target(/* param2= */arg2, /* param1= */arg1); + } + } + """) .doTest(); } @@ -189,13 +215,15 @@ public void namedParametersChecker_suggestsSwap_withOneCommentedSwappedArgs() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param1, Object param2);", - " void test(Object arg1, Object arg2) {", - " // BUG: Diagnostic contains: 'target(/* param1= */arg2, arg1);'", - " target(/* param2= */arg2, arg1);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param1, Object param2); + void test(Object arg1, Object arg2) { + // BUG: Diagnostic contains: 'target(/* param1= */arg2, arg1);' + target(/* param2= */arg2, arg1); + } + } + """) .doTest(); } @@ -204,12 +232,14 @@ public void namedParametersChecker_toleratesApproximateComment_onRequiredNamesMe testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param);", - " void test(Object arg) {", - " target(/*note param = */arg);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param); + void test(Object arg) { + target(/*note param = */arg); + } + } + """) .doTest(); } @@ -218,12 +248,14 @@ public void namedParametersChecker_tolerateComment_withNoEquals() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param);", - " void test(Object arg) {", - " target(/*param*/arg);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param); + void test(Object arg) { + target(/*param*/arg); + } + } + """) .doTest(); } @@ -232,12 +264,14 @@ public void namedParametersChecker_toleratesMatchingComment_blockAfter() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param);", - " void test(Object arg) {", - " target(arg/*param*/);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param); + void test(Object arg) { + target(arg/*param*/); + } + } + """) .doTest(); } @@ -246,12 +280,14 @@ public void namedParametersChecker_toleratesApproximateComment_blockAfter() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param);", - " void test(Object arg) {", - " target(arg/*imprecise match for param*/);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param); + void test(Object arg) { + target(arg/*imprecise match for param*/); + } + } + """) .doTest(); } @@ -260,12 +296,14 @@ public void namedParametersChecker_toleratesMatchingComment_lineAfter() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param);", - " void test(Object arg) {", - " target(arg); //param", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param); + void test(Object arg) { + target(arg); //param + } + } + """) .doTest(); } @@ -279,12 +317,14 @@ public void namedParametersChecker_multipleComments_allowedIfAnyMatch() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void test(Object x) {", - " test(/* y= */ /* x= */ x);", - " test(/* x= */ /* y= */ x);", - " }", - "}") + """ + class Test { + void test(Object x) { + test(/* y= */ /* x= */ x); + test(/* x= */ /* y= */ x); + } + } + """) .doTest(); } @@ -293,12 +333,14 @@ public void namedParametersChecker_multipleComments_flaggedIfNoneMatch() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void test(Object x) {", - " // BUG: Diagnostic contains: does not match", - " test(/* y= */ /* z= */ x);", - " }", - "}") + """ + class Test { + void test(Object x) { + // BUG: Diagnostic contains: does not match + test(/* y= */ /* z= */ x); + } + } + """) .doTest(); } @@ -307,12 +349,14 @@ public void namedParametersChecker_ignoresComment_nonMatchinglineAfter() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param);", - " void test(Object arg) {", - " target(arg); // some_other_comment", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param); + void test(Object arg) { + target(arg); // some_other_comment + } + } + """) .doTest(); } @@ -321,14 +365,16 @@ public void namedParametersChecker_ignoresComment_markedUpDelimiter() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param1, Object param2);", - " void test(Object arg1, Object arg2) {", - " target(arg1,", - " /* ---- param1 <-> param2 ---- */", - " arg2);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param1, Object param2); + void test(Object arg1, Object arg2) { + target(arg1, + /* ---- param1 <-> param2 ---- */ + arg2); + } + } + """) .doTest(); } @@ -337,14 +383,16 @@ public void namedParametersChecker_ignoresLineComments() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void test(int x) {", - " test(", - " // newX =", - " // (x ^ 2)", - " x * x);", - " }", - "}") + """ + class Test { + void test(int x) { + test( + // newX = + // (x ^ 2) + x * x); + } + } + """) .doTest(); } @@ -353,12 +401,14 @@ public void namedParametersChecker_ignoresComment_wrongNameWithNoEquals() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param);", - " void test(Object arg) {", - " target(/* some_other_comment */arg);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param); + void test(Object arg) { + target(/* some_other_comment */arg); + } + } + """) .doTest(); } @@ -367,12 +417,14 @@ public void namedParametersChecker_ignoresComment_wrongVarargs() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object... param);", - " void test(Object arg) {", - " target(/* param.!.= */arg);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object... param); + void test(Object arg) { + target(/* param.!.= */arg); + } + } + """) .doTest(); } @@ -381,13 +433,15 @@ public void namedParametersChecker_matchesComment_withChainedMethod() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract Test getTest(Object param);", - " abstract void target(Object param2);", - " void test(Object arg, Object arg2) {", - " getTest(/* param= */arg).target(arg2);", - " }", - "}") + """ + abstract class Test { + abstract Test getTest(Object param); + abstract void target(Object param2); + void test(Object arg, Object arg2) { + getTest(/* param= */arg).target(arg2); + } + } + """) .doTest(); } @@ -396,15 +450,17 @@ public void namedParametersChecker_suggestsChangeComment_whenNoMatchingNames() { testHelper .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void target(Object param1, Object param2);", - " void test(Object arg1, Object arg2) {", - " // BUG: Diagnostic contains:", - " // target(/* param1= */arg1, arg2)", - " // `/* notMatching= */` does not match formal parameter name `param1`", - " target(/* notMatching= */arg1, arg2);", - " }", - "}") + """ + abstract class Test { + abstract void target(Object param1, Object param2); + void test(Object arg1, Object arg2) { + // BUG: Diagnostic contains: + // target(/* param1= */arg1, arg2) + // `/* notMatching= */` does not match formal parameter name `param1` + target(/* notMatching= */arg1, arg2); + } + } + """) .doTest(); } @@ -493,15 +549,17 @@ public void internalAnnotatedParameterNegative() { testHelper .addSourceLines( "Test.java", - "class Test {", - " public static class AnnotatedParametersTestClass {", - " public @interface Annotated {}", - " public static void target(@Annotated int foo) {}", - " }", - " void test() {", - " AnnotatedParametersTestClass.target(/* foo= */ 1);", - " }", - "}") + """ + class Test { + public static class AnnotatedParametersTestClass { + public @interface Annotated {} + public static void target(@Annotated int foo) {} + } + void test() { + AnnotatedParametersTestClass.target(/* foo= */ 1); + } + } + """) .doTest(); } @@ -510,16 +568,18 @@ public void internalAnnotatedParameterPositive() { testHelper .addSourceLines( "Test.java", - "class Test {", - " public static class AnnotatedParametersTestClass {", - " public @interface Annotated {}", - " public static void target(@Annotated int foo) {}", - " }", - " void test() {", - " // BUG: Diagnostic contains: target(/* foo= */ 1)", - " AnnotatedParametersTestClass.target(/* bar= */ 1);", - " }", - "}") + """ + class Test { + public static class AnnotatedParametersTestClass { + public @interface Annotated {} + public static void target(@Annotated int foo) {} + } + void test() { + // BUG: Diagnostic contains: target(/* foo= */ 1) + AnnotatedParametersTestClass.target(/* bar= */ 1); + } + } + """) .doTest(); } @@ -568,15 +628,17 @@ public void positiveVarargs() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " // BUG: Diagnostic contains: /* args...= */", - " // /* argh */", - " foo(/* argh...= */ 1, 2, 3);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + // BUG: Diagnostic contains: /* args...= */ + // /* argh */ + foo(/* argh...= */ 1, 2, 3); + } + } + """) .doTest(); } @@ -585,15 +647,17 @@ public void emptyVarargs_shouldNotCrash() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int first, int... rest) {}", - "", - " void bar() {", - " foo(/* first= */ 1);", - " // BUG: Diagnostic contains: /* first= */", - " foo(/* second= */ 1);", - " }", - "}") + """ + class Test { + void foo(int first, int... rest) {} + + void bar() { + foo(/* first= */ 1); + // BUG: Diagnostic contains: /* first= */ + foo(/* second= */ 1); + } + } + """) .doTest(); } @@ -602,13 +666,15 @@ public void negativeVarargs() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " foo(/* args...= */ 1, 2);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + foo(/* args...= */ 1, 2); + } + } + """) .doTest(); } @@ -617,14 +683,16 @@ public void varargsCommentAllowedWithArraySyntax() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " int[] myInts = {1, 2, 3};", - " foo(/* args...= */ myInts);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + int[] myInts = {1, 2, 3}; + foo(/* args...= */ myInts); + } + } + """) .doTest(); } @@ -634,15 +702,17 @@ public void normalCommentNotAllowedWithVarargsArraySyntax() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " int[] myInts = {1, 2, 3};", - " // BUG: Diagnostic contains: /* args...= */", - " foo(/* args= */ myInts);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + int[] myInts = {1, 2, 3}; + // BUG: Diagnostic contains: /* args...= */ + foo(/* args= */ myInts); + } + } + """) .doTest(); } @@ -651,15 +721,16 @@ public void varargsCommentAllowedOnOnlyFirstArg() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " // BUG: Diagnostic contains: parameter name comment only allowed on first varargs" - + " argument", - " foo(1, /* args...= */ 2);", - " }", - "}") + """ +class Test { + void foo(int... args) {} + + void bar() { + // BUG: Diagnostic contains: parameter name comment only allowed on first varargs argument + foo(1, /* args...= */ 2); + } +} +""") .doTest(); } @@ -668,22 +739,26 @@ public void varargsWrongFormat() { BugCheckerRefactoringTestHelper.newInstance(ParameterName.class, getClass()) .addInputLines( "in/Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " foo(/* args= */ 1, 2);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + foo(/* args= */ 1, 2); + } + } + """) .addOutputLines( "out/Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " foo(/* args...= */ 1, 2);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + foo(/* args...= */ 1, 2); + } + } + """) .doTest(TEXT_MATCH); } @@ -692,24 +767,28 @@ public void varargsTrailing() { BugCheckerRefactoringTestHelper.newInstance(ParameterName.class, getClass()) .addInputLines( "in/Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " foo(1, /* foo= */ 2);", - " foo(1, /* foo...= */ 2);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + foo(1, /* foo= */ 2); + foo(1, /* foo...= */ 2); + } + } + """) .addOutputLines( "out/Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " foo(1, /* foo */ 2);", - " foo(1, /* foo... */ 2);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + foo(1, /* foo */ 2); + foo(1, /* foo... */ 2); + } + } + """) .doTest(TEXT_MATCH); } @@ -718,13 +797,15 @@ public void varargsIgnoreNonParameterNameComments() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " foo(/* fake */ 1, 2);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + foo(/* fake */ 1, 2); + } + } + """) .doTest(); } @@ -733,15 +814,17 @@ public void varargsWrongNameAndWrongFormat() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int... args) {}", - "", - " void bar() {", - " // BUG: Diagnostic contains: /* args...= */", - " // /* argh */", - " foo(/* argh= */ 1, 2);", - " }", - "}") + """ + class Test { + void foo(int... args) {} + + void bar() { + // BUG: Diagnostic contains: /* args...= */ + // /* argh */ + foo(/* argh= */ 1, 2); + } + } + """) .doTest(); } @@ -750,14 +833,16 @@ public void varargsCommentNotAllowedOnNormalArg() { testHelper .addSourceLines( "Test.java", - "class Test {", - " void foo(int i) {}", - "", - " void bar() {", - " // BUG: Diagnostic contains: /* i= */", - " foo(/* i...= */ 1);", - " }", - "}") + """ + class Test { + void foo(int i) {} + + void bar() { + // BUG: Diagnostic contains: /* i= */ + foo(/* i...= */ 1); + } + } + """) .doTest(); } @@ -789,35 +874,43 @@ public void exemptPackage() { CompilationTestHelper.newInstance(ParameterName.class, getClass()) .addSourceLines( "test/a/A.java", - "package test.a;", - "public class A {", - " public static void f(int value) {}", - "}") + """ + package test.a; + public class A { + public static void f(int value) {} + } + """) .addSourceLines( "test/b/nested/B.java", - "package test.b.nested;", - "public class B {", - " public static void f(int value) {}", - "}") + """ + package test.b.nested; + public class B { + public static void f(int value) {} + } + """) .addSourceLines( "test/c/C.java", - "package test.c;", - "public class C {", - " public static void f(int value) {}", - "}") - .addSourceLines( - "Test.java", - "import test.a.A;", - "import test.b.nested.B;", - "import test.c.C;", - "class Test {", - " void f() {", - " A.f(/* typo= */ 1);", - " B.f(/* typo= */ 1);", - " // BUG: Diagnostic contains: 'C.f(/* value= */ 1);'", - " C.f(/* typo= */ 1);", - " }", - "}") + """ + package test.c; + public class C { + public static void f(int value) {} + } + """) + .addSourceLines( + "Test.java", + """ + import test.a.A; + import test.b.nested.B; + import test.c.C; + class Test { + void f() { + A.f(/* typo= */ 1); + B.f(/* typo= */ 1); + // BUG: Diagnostic contains: 'C.f(/* value= */ 1);' + C.f(/* typo= */ 1); + } + } + """) .setArgs(ImmutableList.of("-XepOpt:ParameterName:exemptPackagePrefixes=test.a,test.b")) .doTest(); } @@ -827,12 +920,14 @@ public void nonCanonicalMockitoImport() { testHelper .addSourceLines( "test/a/A.java", - "package test.a;", - "import static org.mockito.Mockito.eq;", - "public class A {", - " // BUG: Diagnostic contains:", - " Object x = eq(/* notValue= */ 1);", - "}") + """ + package test.a; + import static org.mockito.Mockito.eq; + public class A { + // BUG: Diagnostic contains: + Object x = eq(/* notValue= */ 1); + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/RedundantOverrideTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/RedundantOverrideTest.java index ea08fb505fa..932f6e41249 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/RedundantOverrideTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/RedundantOverrideTest.java @@ -32,20 +32,24 @@ public void positive() { testHelper .addSourceLines( "Test.java", - "class Test extends foo.Bar {", - " // BUG: Diagnostic contains:", - " @Override public boolean frob(Object o) {", - " return super.frob(o);", - " }", - "}") + """ + class Test extends foo.Bar { + // BUG: Diagnostic contains: + @Override public boolean frob(Object o) { + return super.frob(o); + } + } + """) .addSourceLines( "foo/Bar.java", - "package foo;", - "public class Bar {", - " public boolean frob(Object o) {", - " return false;", - " }", - "}") + """ + package foo; + public class Bar { + public boolean frob(Object o) { + return false; + } + } + """) .doTest(); } @@ -54,20 +58,24 @@ public void addingJavadoc() { testHelper .addSourceLines( "Test.java", - "class Test extends foo.Bar {", - " /** Adding javadoc. */", - " @Override public boolean frob(Object o) {", - " return super.frob(o);", - " }", - "}") + """ + class Test extends foo.Bar { + /** Adding javadoc. */ + @Override public boolean frob(Object o) { + return super.frob(o); + } + } + """) .addSourceLines( "foo/Bar.java", - "package foo;", - "public class Bar {", - " public boolean frob(Object o) {", - " return false;", - " }", - "}") + """ + package foo; + public class Bar { + public boolean frob(Object o) { + return false; + } + } + """) .doTest(); } @@ -76,20 +84,24 @@ public void addingComments() { testHelper .addSourceLines( "Test.java", - "class Test extends foo.Bar {", - " @Override public boolean frob(Object o) {", - " // TODO..", - " return super.frob(o);", - " }", - "}") + """ + class Test extends foo.Bar { + @Override public boolean frob(Object o) { + // TODO.. + return super.frob(o); + } + } + """) .addSourceLines( "foo/Bar.java", - "package foo;", - "public class Bar {", - " public boolean frob(Object o) {", - " return false;", - " }", - "}") + """ + package foo; + public class Bar { + public boolean frob(Object o) { + return false; + } + } + """) .doTest(); } @@ -97,17 +109,21 @@ public void addingComments() { public void considersParameterOrder() { testHelper .addSourceLines( - "A.java", // - "class A {", - " public void swap(int a, int b) {}", - "}") + "A.java", + """ + class A { + public void swap(int a, int b) {} + } + """) .addSourceLines( "B.java", - "class B extends A {", - " @Override public void swap(int a, int b) {", - " super.swap(b, a);", - " }", - "}") + """ + class B extends A { + @Override public void swap(int a, int b) { + super.swap(b, a); + } + } + """) .doTest(); } @@ -115,17 +131,21 @@ public void considersParameterOrder() { public void wideningVisibilityNoMatch() { testHelper .addSourceLines( - "A.java", // - "class A {", - " void swap(int a, int b) {}", - "}") + "A.java", + """ + class A { + void swap(int a, int b) {} + } + """) .addSourceLines( "B.java", - "class B extends A {", - " @Override public void swap(int a, int b) {", - " super.swap(a, b);", - " }", - "}") + """ + class B extends A { + @Override public void swap(int a, int b) { + super.swap(a, b); + } + } + """) .doTest(); } @@ -133,21 +153,25 @@ public void wideningVisibilityNoMatch() { public void addingAnnotations() { testHelper .addSourceLines( - "A.java", // - "class A {", - " Object swap(int a, int b) {", - " return null;", - " }", - "}") + "A.java", + """ + class A { + Object swap(int a, int b) { + return null; + } + } + """) .addSourceLines( "B.java", - "import javax.annotation.Nullable;", - "class B extends A {", - " @Nullable", - " @Override public Object swap(int a, int b) {", - " return super.swap(a, b);", - " }", - "}") + """ + import javax.annotation.Nullable; + class B extends A { + @Nullable + @Override public Object swap(int a, int b) { + return super.swap(a, b); + } + } + """) .doTest(); } @@ -155,23 +179,27 @@ public void addingAnnotations() { public void sameAnnotation() { testHelper .addSourceLines( - "A.java", // - "import javax.annotation.Nullable;", - "class A {", - " @Nullable Object swap(int a, int b) {", - " return null;", - " }", - "}") + "A.java", + """ + import javax.annotation.Nullable; + class A { + @Nullable Object swap(int a, int b) { + return null; + } + } + """) .addSourceLines( "B.java", - "import javax.annotation.Nullable;", - "class B extends A {", - " @Nullable", - " // BUG: Diagnostic contains:", - " @Override Object swap(int a, int b) {", - " return super.swap(a, b);", - " }", - "}") + """ + import javax.annotation.Nullable; + class B extends A { + @Nullable + // BUG: Diagnostic contains: + @Override Object swap(int a, int b) { + return super.swap(a, b); + } + } + """) .doTest(); } @@ -179,21 +207,25 @@ public void sameAnnotation() { public void removesAnnotation() { testHelper .addSourceLines( - "A.java", // - "import javax.annotation.Nullable;", - "class A {", - " @Nullable Object swap(int a, int b) {", - " return null;", - " }", - "}") + "A.java", + """ + import javax.annotation.Nullable; + class A { + @Nullable Object swap(int a, int b) { + return null; + } + } + """) .addSourceLines( "B.java", - "import javax.annotation.Nullable;", - "class B extends A {", - " @Override Object swap(int a, int b) {", - " return super.swap(a, b);", - " }", - "}") + """ + import javax.annotation.Nullable; + class B extends A { + @Override Object swap(int a, int b) { + return super.swap(a, b); + } + } + """) .doTest(); } @@ -201,21 +233,25 @@ public void removesAnnotation() { public void addsAnnotation() { testHelper .addSourceLines( - "A.java", // - "class A {", - " Object swap(int a, int b) {", - " return null;", - " }", - "}") + "A.java", + """ + class A { + Object swap(int a, int b) { + return null; + } + } + """) .addSourceLines( "B.java", - "import javax.annotation.Nullable;", - "class B extends A {", - " @Nullable", - " @Override Object swap(int a, int b) {", - " return super.swap(a, b);", - " }", - "}") + """ + import javax.annotation.Nullable; + class B extends A { + @Nullable + @Override Object swap(int a, int b) { + return super.swap(a, b); + } + } + """) .doTest(); } @@ -223,19 +259,23 @@ public void addsAnnotation() { public void protectedOverrideInDifferentPackage() { testHelper .addSourceLines( - "A.java", // - "package foo;", - "public class A {", - " protected void swap() {}", - "}") + "A.java", + """ + package foo; + public class A { + protected void swap() {} + } + """) .addSourceLines( "B.java", - "package bar;", - "public class B extends foo.A {", - " @Override protected void swap() {", - " super.swap();", - " }", - "}") + """ + package bar; + public class B extends foo.A { + @Override protected void swap() { + super.swap(); + } + } + """) .doTest(); } @@ -243,20 +283,24 @@ public void protectedOverrideInDifferentPackage() { public void protectedOverrideInSamePackage() { testHelper .addSourceLines( - "A.java", // - "package foo;", - "class A {", - " protected void swap() {}", - "}") + "A.java", + """ + package foo; + class A { + protected void swap() {} + } + """) .addSourceLines( "B.java", - "package foo;", - "class B extends A {", - " // BUG: Diagnostic contains:", - " @Override protected void swap() {", - " super.swap();", - " }", - "}") + """ + package foo; + class B extends A { + // BUG: Diagnostic contains: + @Override protected void swap() { + super.swap(); + } + } + """) .doTest(); } @@ -264,24 +308,30 @@ public void protectedOverrideInSamePackage() { public void paramAnnotationAddedInOverride() { testHelper .addSourceLines( - "DemoAnnotation.java", // - "package foo;", - "@interface DemoAnnotation {}") + "DemoAnnotation.java", + """ + package foo; + @interface DemoAnnotation {} + """) .addSourceLines( - "A.java", // - "package foo;", - "class A {", - " protected void swap(int a) {}", - "}") + "A.java", + """ + package foo; + class A { + protected void swap(int a) {} + } + """) .addSourceLines( "B.java", - "package foo;", - "class B extends A {", - " @Override", - " protected void swap(@DemoAnnotation int a) {", - " super.swap(a);", - " }", - "}") + """ + package foo; + class B extends A { + @Override + protected void swap(@DemoAnnotation int a) { + super.swap(a); + } + } + """) .doTest(); } @@ -289,24 +339,30 @@ public void paramAnnotationAddedInOverride() { public void paramAnnotationOmittedInOverride() { testHelper .addSourceLines( - "DemoAnnotation.java", // - "package foo;", - "@interface DemoAnnotation {}") + "DemoAnnotation.java", + """ + package foo; + @interface DemoAnnotation {} + """) .addSourceLines( - "A.java", // - "package foo;", - "class A {", - " protected void swap(@DemoAnnotation int a) {}", - "}") + "A.java", + """ + package foo; + class A { + protected void swap(@DemoAnnotation int a) {} + } + """) .addSourceLines( "B.java", - "package foo;", - "class B extends A {", - " @Override", - " protected void swap(int a) {", - " super.swap(a);", - " }", - "}") + """ + package foo; + class B extends A { + @Override + protected void swap(int a) { + super.swap(a); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/TransientMisuseTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/TransientMisuseTest.java index ee55d592040..73582788b29 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/TransientMisuseTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/TransientMisuseTest.java @@ -33,16 +33,18 @@ public void positive() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " // BUG: Diagnostic contains: static String foo1", - " static transient String foo1;", - " // BUG: Diagnostic contains: static String foo2", - " transient static String foo2;", - " // BUG: Diagnostic contains: static final public String foo3", - " static final public transient String foo3 = \"\";", - " // BUG: Diagnostic contains: protected final static String foo4", - " protected final static transient String foo4 = \"\";", - "}") + """ + class Test { + // BUG: Diagnostic contains: static String foo1 + static transient String foo1; + // BUG: Diagnostic contains: static String foo2 + transient static String foo2; + // BUG: Diagnostic contains: static final public String foo3 + static final public transient String foo3 = ""; + // BUG: Diagnostic contains: protected final static String foo4 + protected final static transient String foo4 = ""; + } + """) .doTest(); } @@ -50,10 +52,12 @@ public void positive() { public void negative() { compilationHelper .addSourceLines( - "Test.java", // - "class Test {", - " static String foo;", - "}") + "Test.java", + """ + class Test { + static String foo; + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UngroupedOverloadsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UngroupedOverloadsTest.java index f7be58d98a3..3b842f94408 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UngroupedOverloadsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UngroupedOverloadsTest.java @@ -102,20 +102,24 @@ public void ungroupedOverloadsRefactoringBelowCutoffLimit() { refactoringHelper .addInputLines( "in/BelowLimit.java", - "class BelowLimit {", - " BelowLimit() {}", - " void foo() {}", - " void bar() {}", - " void foo(int x) {}", - "}") + """ + class BelowLimit { + BelowLimit() {} + void foo() {} + void bar() {} + void foo(int x) {} + } + """) .addOutputLines( "out/BelowLimit.java", - "class BelowLimit {", - " BelowLimit() {}", - " void foo() {}", - " void foo(int x) {}", - " void bar() {}", - "}") + """ + class BelowLimit { + BelowLimit() {} + void foo() {} + void foo(int x) {} + void bar() {} + } + """) .doTest(); } @@ -124,22 +128,26 @@ public void ungroupedOverloadsRefactoring_fiveMethods() { refactoringHelper .addInputLines( "in/AboveLimit.java", - "class AboveLimit {", - " AboveLimit() {}", - " void foo() {}", - " void bar() {}", - " void foo(int x) {}", - " void baz() {}", - "}") + """ + class AboveLimit { + AboveLimit() {} + void foo() {} + void bar() {} + void foo(int x) {} + void baz() {} + } + """) .addOutputLines( "out/AboveLimit.java", - "class AboveLimit {", - " AboveLimit() {}", - " void foo() {}", - " void foo(int x) {}", - " void bar() {}", - " void baz() {}", - "}") + """ + class AboveLimit { + AboveLimit() {} + void foo() {} + void foo(int x) {} + void bar() {} + void baz() {} + } + """) .doTest(); } @@ -149,11 +157,13 @@ public void staticAndNonStatic() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " void foo() {}", - " void bar() {}", - " static void foo(int x) {}", - "}") + """ + class Test { + void foo() {} + void bar() {} + static void foo(int x) {} + } + """) .expectUnchanged() .doTest(); } @@ -163,11 +173,13 @@ public void staticAndNonStaticInterspersed() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " private void foo(int x) {}", - " private static void foo(int x, int y, int z) {}", - " private void foo(int x, int y) {}", - "}") + """ + class Test { + private void foo(int x) {} + private static void foo(int x, int y, int z) {} + private void foo(int x, int y) {} + } + """) .doTest(); } @@ -176,11 +188,13 @@ public void suppressOnAnyMethod() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " void foo() {}", - " void bar() {}", - " @SuppressWarnings(\"UngroupedOverloads\") void foo(int x) {}", - "}") + """ + class Test { + void foo() {} + void bar() {} + @SuppressWarnings("UngroupedOverloads") void foo(int x) {} + } + """) .doTest(); } @@ -189,22 +203,26 @@ public void javadoc() { refactoringHelper .addInputLines( "in/Test.java", - "class Test {", - " void foo() {}", - " void bar() {}", - " /** doc */", - " void foo(int x) {}", - "}") + """ + class Test { + void foo() {} + void bar() {} + /** doc */ + void foo(int x) {} + } + """) .addOutputLines( "out/Test.java", - "class Test {", - "", - " void foo() {}", - " /** doc */", - " void foo(int x) {}", - "", - " void bar() {}", - "}") + """ + class Test { + + void foo() {} + /** doc */ + void foo(int x) {} + + void bar() {} + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -213,19 +231,21 @@ public void diagnostic() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 8, 10, 12", - " private void foo() {}", - " // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 8, 10, 12", - " private void foo(int a) {}", - " private void bar() {}", - " // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 3, 5", - " private void foo(int a, int b) {}", - " // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 3, 5", - " private void foo(int a, int b, int c) {}", - " // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 3, 5", - " private void foo(int a, int b, int c, int d) {}", - "}") + """ + class Test { + // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 8, 10, 12 + private void foo() {} + // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 8, 10, 12 + private void foo(int a) {} + private void bar() {} + // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 3, 5 + private void foo(int a, int b) {} + // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 3, 5 + private void foo(int a, int b, int c) {} + // BUG: Diagnostic contains: ungrouped overloads of 'foo' on line(s): 3, 5 + private void foo(int a, int b, int c, int d) {} + } + """) .doTest(); } @@ -234,43 +254,47 @@ public void interleavedUngroupedOverloads() { refactoringHelper .addInputLines( "in/Test.java", - "class Test {", - " void foo() {", - " System.err.println();", - " }", - "", - " void bar() {", - " System.err.println();", - " }", - "", - " void foo(int x) {", - " System.err.println();", - " }", - "", - " void bar(int x) {", - " System.err.println();", - " }", - "}") + """ + class Test { + void foo() { + System.err.println(); + } + + void bar() { + System.err.println(); + } + + void foo(int x) { + System.err.println(); + } + + void bar(int x) { + System.err.println(); + } + } + """) .addOutputLines( "out/Test.java", - "class Test {", - "", - " void foo() {", - " System.err.println();", - " }", - "", - " void foo(int x) {", - " System.err.println();", - " }", - "", - " void bar() {", - " System.err.println();", - " }", - "", - " void bar(int x) {", - " System.err.println();", - " }", - "}") + """ + class Test { + + void foo() { + System.err.println(); + } + + void foo(int x) { + System.err.println(); + } + + void bar() { + System.err.println(); + } + + void bar(int x) { + System.err.println(); + } + } + """) .setArgs("-XepOpt:UngroupedOverloads:BatchFindings") .doTest(TestMode.TEXT_MATCH); } @@ -280,13 +304,15 @@ public void describingConstructors() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " // BUG: Diagnostic contains: constructor overloads", - " Test() {}", - " private void bar() {}", - " // BUG: Diagnostic contains: constructor overloads", - " Test(int i) {}", - "}") + """ + class Test { + // BUG: Diagnostic contains: constructor overloads + Test() {} + private void bar() {} + // BUG: Diagnostic contains: constructor overloads + Test(int i) {} + } + """) .doTest(); } @@ -297,14 +323,16 @@ public void recordConstructor() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableSet;", - "import java.util.Set;", - "", - "record MyRecord(ImmutableSet strings) {", - " MyRecord(Set strings) {", - " this(strings == null ? ImmutableSet.of() : ImmutableSet.copyOf(strings));", - " }", - "}") + """ + import com.google.common.collect.ImmutableSet; + import java.util.Set; + + record MyRecord(ImmutableSet strings) { + MyRecord(Set strings) { + this(strings == null ? ImmutableSet.of() : ImmutableSet.copyOf(strings)); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnicodeEscapeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnicodeEscapeTest.java index 9622db9324b..3ab4ac1addd 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnicodeEscapeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnicodeEscapeTest.java @@ -37,10 +37,12 @@ public void printableAsciiCharacter_finding() { helper .addSourceLines( "Test.java", - "class Test {", - " // BUG: Diagnostic contains:", - " private static final String FOO = \"\\u0020\";", - "}") + """ + class Test { + // BUG: Diagnostic contains: + private static final String FOO = "\\u0020"; + } + """) .doTest(); } @@ -49,10 +51,12 @@ public void suppression() { helper .addSourceLines( "Test.java", - "@SuppressWarnings(\"UnicodeEscape\")", - "class Test {", - " private static final String FOO = \"\\u0020\";", - "}") + """ + @SuppressWarnings("UnicodeEscape") + class Test { + private static final String FOO = "\\u0020"; + } + """) .doTest(); } @@ -60,17 +64,21 @@ public void suppression() { public void unicodeEscapeRefactoredToLiteral() { refactoring .addInputLines( - "Test.java", // - "class Test {", - " private static final String FOO = \"\\u0020\";", - " private static final String BAR = \"\\uuuuu0020\";", - "}") + "Test.java", + """ + class Test { + private static final String FOO = "\\u0020"; + private static final String BAR = "\\uuuuu0020"; + } + """) .addOutputLines( - "Test.java", // - "class Test {", - " private static final String FOO = \" \";", - " private static final String BAR = \" \";", - "}") + "Test.java", + """ + class Test { + private static final String FOO = " "; + private static final String BAR = " "; + } + """) .doTest(TEXT_MATCH); } @@ -78,15 +86,19 @@ public void unicodeEscapeRefactoredToLiteral() { public void jdk8269150() { refactoring .addInputLines( - "Test.java", // - "class Test {", - " private static final String FOO = \"\\u005c\\\\u005d\";", - "}") + "Test.java", + """ + class Test { + private static final String FOO = "\\u005c\\\\u005d"; + } + """) .addOutputLines( - "Test.java", // - "class Test {", - " private static final String FOO = \"\\\\]\";", - "}") + "Test.java", + """ + class Test { + private static final String FOO = "\\\\]"; + } + """) .doTest(TEXT_MATCH); } @@ -108,10 +120,12 @@ public void newlinesRefactored() { public void nonPrintableAsciiCharacter_noFinding() { helper .addSourceLines( - "Test.java", // - "class Test {", - " private static final String FOO = \"\\u0312\";", - "}") + "Test.java", + """ + class Test { + private static final String FOO = "\\u0312"; + } + """) .doTest(); } @@ -119,10 +133,12 @@ public void nonPrintableAsciiCharacter_noFinding() { public void extraEscapes_noFinding() { helper .addSourceLines( - "Test.java", // - "class Test {", - " private static final String FOO = \"\\\\u0020\";", - "}") + "Test.java", + """ + class Test { + private static final String FOO = "\\\\u0020"; + } + """) .doTest(); } @@ -138,9 +154,11 @@ public void everythingObfuscated() { public void escapedLiteralBackslashU() { refactoring .addInputLines( - "A.java", // - "/** \\u005Cu */", - "class A {}") + "A.java", + """ + /** \\u005Cu */ + class A {} + """) .expectUnchanged() .doTest(TEXT_MATCH); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryTypeArgumentTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryTypeArgumentTest.java index 9c5893ce65e..995e50e0c68 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryTypeArgumentTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryTypeArgumentTest.java @@ -33,14 +33,16 @@ public void positiveCall() { compilationHelper .addSourceLines( "Test.java", - "package foo.bar;", - "class Test {", - " void f() {}", - " void m() {", - " // BUG: Diagnostic contains: this.f()", - " this.f();", - " }", - "}") + """ + package foo.bar; + class Test { + void f() {} + void m() { + // BUG: Diagnostic contains: this.f() + this.f(); + } + } + """) .doTest(); } @@ -49,17 +51,19 @@ public void positiveThis() { compilationHelper .addSourceLines( "Test.java", - "package foo.bar;", - "class Test {", - " static class C {", - " public C() {", - " // BUG: Diagnostic contains: /*START*/this(42)", - " /*START*/this(42);", - " }", - " public C(int i) {", - " }", - " }", - "}") + """ + package foo.bar; + class Test { + static class C { + public C() { + // BUG: Diagnostic contains: /*START*/this(42) + /*START*/this(42); + } + public C(int i) { + } + } + } + """) .doTest(); } @@ -68,19 +72,21 @@ public void positiveSuper() { compilationHelper .addSourceLines( "Test.java", - "package foo.bar;", - "class Test {", - " static class B {", - " public B() {", - " }", - " }", - " static class C extends B {", - " public C() {", - " // BUG: Diagnostic contains: /*START*/super()", - " /*START*/super();", - " }", - " }", - "}") + """ + package foo.bar; + class Test { + static class B { + public B() { + } + } + static class C extends B { + public C() { + // BUG: Diagnostic contains: /*START*/super() + /*START*/super(); + } + } + } + """) .doTest(); } @@ -89,16 +95,18 @@ public void positiveInstantiation() { compilationHelper .addSourceLines( "Test.java", - "package foo.bar;", - "class Test {", - " static class C {", - " public C() {}", - " }", - " void m() {", - " // BUG: Diagnostic contains: new C()", - " new C();", - " }", - "}") + """ + package foo.bar; + class Test { + static class C { + public C() {} + } + void m() { + // BUG: Diagnostic contains: new C() + new C(); + } + } + """) .doTest(); } @@ -107,13 +115,15 @@ public void negative() { compilationHelper .addSourceLines( "Test.java", - "package foo.bar;", - "class Test {", - " void f() {}", - " void m() {", - " this.f();", - " }", - "}") + """ + package foo.bar; + class Test { + void f() {} + void m() { + this.f(); + } + } + """) .doTest(); } @@ -121,20 +131,29 @@ public void negative() { public void negativeGenericSuper() { compilationHelper .addSourceLines( - "Super.java", "public class Super {", " public T f(T x) { return x; }", "}") + "Super.java", + """ + public class Super { + public T f(T x) { return x; } + } + """) .addSourceLines( "Sub.java", - "@SuppressWarnings(\"unchecked\")", - "public class Sub extends Super {", - " public Object f(Object x) { return x; }", - "}") + """ + @SuppressWarnings("unchecked") + public class Sub extends Super { + public Object f(Object x) { return x; } + } + """) .addSourceLines( "Test.java", - "public class Test {", - " void m(Sub s) {", - " s.f(null);", - " }", - "}") + """ + public class Test { + void m(Sub s) { + s.f(null); + } + } + """) .doTest(); } @@ -143,14 +162,16 @@ public void whitespaceFix() { compilationHelper .addSourceLines( "Test.java", - "package foo.bar;", - "class Test {", - " void f() {}", - " void m() {", - " // BUG: Diagnostic contains: this.f()", - " this.< /* */ String /* */ >f();", - " }", - "}") + """ + package foo.bar; + class Test { + void f() {} + void m() { + // BUG: Diagnostic contains: this.f() + this.< /* */ String /* */ >f(); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnsafeLocaleUsageTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnsafeLocaleUsageTest.java index a22fc679807..a690f816147 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnsafeLocaleUsageTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnsafeLocaleUsageTest.java @@ -36,34 +36,38 @@ public void unsafeLocaleUsageCheck_constructorUsageWithOneParam_shouldRefactorNo refactoringHelper .addInputLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " static class Inner {", - " private Locale locale;", - " Inner(String a) {", - " locale = new Locale(a);", - " }", - " }", - "", - " private static final Test.Inner INNER_OBJ = new Inner(\"zh_hant_tw\");", - "", - "}") + """ + import java.util.Locale; + + class Test { + static class Inner { + private Locale locale; + Inner(String a) { + locale = new Locale(a); + } + } + + private static final Test.Inner INNER_OBJ = new Inner("zh_hant_tw"); + + } + """) .addOutputLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " static class Inner {", - " private Locale locale;", - " Inner(String a) {", - " locale = Locale.forLanguageTag(a.replace(\"_\", \"-\"));", - " }", - " }", - "", - " private static final Test.Inner INNER_OBJ = new Inner(\"zh_hant_tw\");", - "", - "}") + """ + import java.util.Locale; + + class Test { + static class Inner { + private Locale locale; + Inner(String a) { + locale = Locale.forLanguageTag(a.replace("_", "-")); + } + } + + private static final Test.Inner INNER_OBJ = new Inner("zh_hant_tw"); + + } + """) .doTest(); } @@ -72,18 +76,22 @@ public void unsafeLocaleUsageCheck_constructorUsageWithOneParam_shouldRefactorLi refactoringHelper .addInputLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " private static final Locale LOCALE = new Locale(\"zh_hant_tw\");", - "}") + """ + import java.util.Locale; + + class Test { + private static final Locale LOCALE = new Locale("zh_hant_tw"); + } + """) .addOutputLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " private static final Locale LOCALE = Locale.forLanguageTag(\"zh-hant-tw\");", - "}") + """ + import java.util.Locale; + + class Test { + private static final Locale LOCALE = Locale.forLanguageTag("zh-hant-tw"); + } + """) .doTest(); } @@ -92,34 +100,38 @@ public void unsafeLocaleUsageCheck_constructorUsageWithTwoParams_shouldRefactor( refactoringHelper .addInputLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " static class Inner {", - " private Locale locale;", - " Inner(String a, String b) {", - " locale = new Locale(a, b);", - " }", - " }", - "", - " private static final Test.Inner INNER_OBJ = new Inner(\"zh\", \"tw\");", - "", - "}") + """ + import java.util.Locale; + + class Test { + static class Inner { + private Locale locale; + Inner(String a, String b) { + locale = new Locale(a, b); + } + } + + private static final Test.Inner INNER_OBJ = new Inner("zh", "tw"); + + } + """) .addOutputLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " static class Inner {", - " private Locale locale;", - " Inner(String a, String b) {", - " locale = new Locale.Builder().setLanguage(a).setRegion(b).build();", - " }", - " }", - "", - " private static final Test.Inner INNER_OBJ = new Inner(\"zh\", \"tw\");", - "", - "}") + """ + import java.util.Locale; + + class Test { + static class Inner { + private Locale locale; + Inner(String a, String b) { + locale = new Locale.Builder().setLanguage(a).setRegion(b).build(); + } + } + + private static final Test.Inner INNER_OBJ = new Inner("zh", "tw"); + + } + """) .doTest(); } @@ -128,20 +140,22 @@ public void unsafeLocaleUsageCheck_constructorUsageWithThreeParams_shouldFlag() compilationHelper .addSourceLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " static class Inner {", - " private Locale locale;", - " Inner(String a, String b, String c) {", - " // BUG: Diagnostic contains: forLanguageTag(String)", - " locale = new Locale(a, b, c);", - " }", - " }", - "", - " private static final Test.Inner INNER_OBJ = new Inner(\"zh\", \"tw\", \"hant\");", - "", - "}") + """ + import java.util.Locale; + + class Test { + static class Inner { + private Locale locale; + Inner(String a, String b, String c) { + // BUG: Diagnostic contains: forLanguageTag(String) + locale = new Locale(a, b, c); + } + } + + private static final Test.Inner INNER_OBJ = new Inner("zh", "tw", "hant"); + + } + """) .doTest(); } @@ -150,40 +164,44 @@ public void unsafeLocaleUsageCheck_toStringUsage_shouldRefactor() { refactoringHelper .addInputLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " static class Inner {", - " private Locale locale;", - " Inner(String a) {", - " locale = Locale.forLanguageTag(a);", - " }", - "", - " String getLocaleDisplayString() {", - " return locale.toString();", - " }", - " }", - "", - " private static final Test.Inner INNER_OBJ = new Inner(\"zh_hant_tw\");", - "}") + """ + import java.util.Locale; + + class Test { + static class Inner { + private Locale locale; + Inner(String a) { + locale = Locale.forLanguageTag(a); + } + + String getLocaleDisplayString() { + return locale.toString(); + } + } + + private static final Test.Inner INNER_OBJ = new Inner("zh_hant_tw"); + } + """) .addOutputLines( "Test.java", - "import java.util.Locale;", - "", - "class Test {", - " static class Inner {", - " private Locale locale;", - " Inner(String a) {", - " locale = Locale.forLanguageTag(a);", - " }", - "", - " String getLocaleDisplayString() {", - " return locale.toLanguageTag();", - " }", - " }", - "", - " private static final Test.Inner INNER_OBJ = new Inner(\"zh_hant_tw\");", - "}") + """ + import java.util.Locale; + + class Test { + static class Inner { + private Locale locale; + Inner(String a) { + locale = Locale.forLanguageTag(a); + } + + String getLocaleDisplayString() { + return locale.toLanguageTag(); + } + } + + private static final Test.Inner INNER_OBJ = new Inner("zh_hant_tw"); + } + """) .doTest(); } @@ -192,13 +210,15 @@ public void unsafeLocaleUsageCheck_multipleErrors_shouldFlag() { compilationHelper .addSourceLines( "Test.java", - "import java.util.Locale;", - "class Test {", - " // BUG: Diagnostic contains: forLanguageTag(String)", - " private static final Locale LOCALE = new Locale(", - " // BUG: Diagnostic contains: toLanguageTag()", - " Locale.TAIWAN.toString());", - "}") + """ + import java.util.Locale; + class Test { + // BUG: Diagnostic contains: forLanguageTag(String) + private static final Locale LOCALE = new Locale( + // BUG: Diagnostic contains: toLanguageTag() + Locale.TAIWAN.toString()); + } + """) .doTest(); } @@ -207,17 +227,19 @@ public void unsafeLocaleUsageCheck_instanceMethodUsage_shouldNotFlag() { compilationHelper .addSourceLines( "Test.java", - "import java.util.Locale;", - "import com.google.common.collect.ImmutableMap;", - "class Test {", - " private static final ImmutableMap INTERNAL_COUNTRY_CODE_TO_LOCALE =", - " ImmutableMap.of(\"abc\", Locale.KOREAN);", - " private static final String DISPLAY_NAME = getLocaleDisplayNameFromCode(\"abc\");", - "", - " public static final String getLocaleDisplayNameFromCode(String code) {", - " return INTERNAL_COUNTRY_CODE_TO_LOCALE.get(code).getDisplayName();", - " }", - "}") + """ + import java.util.Locale; + import com.google.common.collect.ImmutableMap; + class Test { + private static final ImmutableMap INTERNAL_COUNTRY_CODE_TO_LOCALE = + ImmutableMap.of("abc", Locale.KOREAN); + private static final String DISPLAY_NAME = getLocaleDisplayNameFromCode("abc"); + + public static final String getLocaleDisplayNameFromCode(String code) { + return INTERNAL_COUNTRY_CODE_TO_LOCALE.get(code).getDisplayName(); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnusedVariableTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnusedVariableTest.java index b7ea0d61e77..8c8f369136e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnusedVariableTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnusedVariableTest.java @@ -40,20 +40,22 @@ public void exemptedByReceiverParameter() { helper .addSourceLines( "ExemptedByReceiverParameter.java", - "package unusedvars;", - "public class ExemptedByReceiverParameter {", - " public void test() {", - " used();", - " }", - " private void used(ExemptedByReceiverParameter this) {", - " // the receiver parameter should not be marked as unused", - " }", - " class Inner {", - " private Inner(ExemptedByReceiverParameter ExemptedByReceiverParameter.this) {", - " // the receiver parameter should not be marked as unused", - " }", - " }", - "}") + """ + package unusedvars; + public class ExemptedByReceiverParameter { + public void test() { + used(); + } + private void used(ExemptedByReceiverParameter this) { + // the receiver parameter should not be marked as unused + } + class Inner { + private Inner(ExemptedByReceiverParameter ExemptedByReceiverParameter.this) { + // the receiver parameter should not be marked as unused + } + } + } + """) .doTest(); } @@ -62,18 +64,20 @@ public void unicodeBytes() { helper .addSourceLines( "UnicodeBytes.java", - "package unusedvars;", - "/**", - " * This file contains Unicode characters: ❁❁❁❁❁❁❁❁❁", - " */", - "public class UnicodeBytes {", - " public void test() {", - " // BUG: Diagnostic contains: is never read", - " int notUsedLocal;", - " String usedLocal = \"\";", - " System.out.println(usedLocal);", - " }", - "}") + """ +package unusedvars; +/** + * This file contains Unicode characters: \u2741\u2741\u2741\u2741\u2741\u2741\u2741\u2741\u2741 + */ +public class UnicodeBytes { + public void test() { + // BUG: Diagnostic contains: is never read + int notUsedLocal; + String usedLocal = ""; + System.out.println(usedLocal); + } +} +""") .doTest(); } @@ -82,16 +86,18 @@ public void unusedArray() { helper .addSourceLines( "UnusedArray.java", - "package unusedvars;", - "public class UnusedArray {", - " private int[] ints;", - " public void test() {", - " ints[0] = 0;", - " ints[0]++;", - " ints[0]--;", - " ints[0] -= 0;", - " }", - "}") + """ + package unusedvars; + public class UnusedArray { + private int[] ints; + public void test() { + ints[0] = 0; + ints[0]++; + ints[0]--; + ints[0] -= 0; + } + } + """) .doTest(); } @@ -100,46 +106,50 @@ public void unusedEnhancedForLoop() { refactoringHelper .addInputLines( "UnusedEnhancedForLoop.java", - "package unusedvars;", - "import java.util.ArrayList;", - "import java.util.List;", - "class UnusedEnhancedForLoop {", - " public List makeList(List input) {", - " List output = new ArrayList<>();", - " for (final String firstVar : input) {", - " output.add(\"a string\");", - " }", - " return output;", - " }", - " public List listData(List> input) {", - " List output = new ArrayList<>();", - " for (List secondVar : input) {", - " output.add(\"a string\");", - " }", - " return output;", - " }", - "}") + """ + package unusedvars; + import java.util.ArrayList; + import java.util.List; + class UnusedEnhancedForLoop { + public List makeList(List input) { + List output = new ArrayList<>(); + for (final String firstVar : input) { + output.add("a string"); + } + return output; + } + public List listData(List> input) { + List output = new ArrayList<>(); + for (List secondVar : input) { + output.add("a string"); + } + return output; + } + } + """) .addOutputLines( "UnusedEnhancedForLoop.java", - "package unusedvars;", - "import java.util.ArrayList;", - "import java.util.List;", - "class UnusedEnhancedForLoop {", - " public List makeList(List input) {", - " List output = new ArrayList<>();", - " for (final String unused : input) {", - " output.add(\"a string\");", - " }", - " return output;", - " }", - " public List listData(List> input) {", - " List output = new ArrayList<>();", - " for (List unused : input) {", - " output.add(\"a string\");", - " }", - " return output;", - " }", - "}") + """ + package unusedvars; + import java.util.ArrayList; + import java.util.List; + class UnusedEnhancedForLoop { + public List makeList(List input) { + List output = new ArrayList<>(); + for (final String unused : input) { + output.add("a string"); + } + return output; + } + public List listData(List> input) { + List output = new ArrayList<>(); + for (List unused : input) { + output.add("a string"); + } + return output; + } + } + """) .doTest(); } @@ -148,35 +158,37 @@ public void unusedField() { helper .addSourceLines( "UnusedField.java", - "package unusedvars;", - "import java.util.ArrayList;", - "import java.util.List;", - "public class UnusedField {", - " // BUG: Diagnostic contains: is never read", - " private int notUsedInt;", - " // BUG: Diagnostic contains: is never read", - " private List list = new ArrayList<>();", - " public void test() {", - " notUsedInt = 0;", - " if (hashCode() > 0) {", - " list = null;", - " } else {", - " list = makeList();", - " }", - " }", - " private List makeList() {", - " return null;", - " }", - " public UnusedField(List list) {", - " this.list = list;", - " }", - " // These fields are special, and should not be flagged as unused.", - " private static final long serialVersionUID = 0;", - " private static final String TAG = \"UnusedFieldTestThingy\";", - " @SuppressWarnings(\"unchecked\")", - " // BUG: Diagnostic contains: is never read", - " private long fieldWithAnn;", - "}") + """ + package unusedvars; + import java.util.ArrayList; + import java.util.List; + public class UnusedField { + // BUG: Diagnostic contains: is never read + private int notUsedInt; + // BUG: Diagnostic contains: is never read + private List list = new ArrayList<>(); + public void test() { + notUsedInt = 0; + if (hashCode() > 0) { + list = null; + } else { + list = makeList(); + } + } + private List makeList() { + return null; + } + public UnusedField(List list) { + this.list = list; + } + // These fields are special, and should not be flagged as unused. + private static final long serialVersionUID = 0; + private static final String TAG = "UnusedFieldTestThingy"; + @SuppressWarnings("unchecked") + // BUG: Diagnostic contains: is never read + private long fieldWithAnn; + } + """) .doTest(); } @@ -207,19 +219,21 @@ public void unusedLocalVarInitialized() { helper .addSourceLines( "UnusedLocalVarInitialized.java", - "package unusedvars;", - "public class UnusedLocalVarInitialized {", - " public void test() {", - " String s = \"\";", - " System.out.println(s);", - " // BUG: Diagnostic contains: is never read", - " int notUsed = UnusedLocalVarInitialized.setData();", - " notUsed = this.hashCode();", - " }", - " public static int setData() {", - " return 0;", - " }", - "}") + """ + package unusedvars; + public class UnusedLocalVarInitialized { + public void test() { + String s = ""; + System.out.println(s); + // BUG: Diagnostic contains: is never read + int notUsed = UnusedLocalVarInitialized.setData(); + notUsed = this.hashCode(); + } + public static int setData() { + return 0; + } + } + """) .doTest(); } @@ -228,28 +242,30 @@ public void unusedLocalVar() { helper .addSourceLines( "UnusedLocalVar.java", - "package unusedvars;", - "public class UnusedLocalVar {", - " public void test() {", - " // BUG: Diagnostic contains: is never read", - " int notUsedLocal;", - " notUsedLocal = 0;", - " String usedLocal = \"\";", - " if (usedLocal.length() == 0) {", - " notUsedLocal = 10 + usedLocal.length();", - " } else {", - " notUsedLocal = this.calculate()", - " + 1 ;", - " notUsedLocal--;", - " notUsedLocal += Integer.valueOf(1);", - " System.out.println(usedLocal);", - " }", - " System.out.println(usedLocal);", - " }", - " int calculate() {", - " return 0;", - " }", - "}") + """ + package unusedvars; + public class UnusedLocalVar { + public void test() { + // BUG: Diagnostic contains: is never read + int notUsedLocal; + notUsedLocal = 0; + String usedLocal = ""; + if (usedLocal.length() == 0) { + notUsedLocal = 10 + usedLocal.length(); + } else { + notUsedLocal = this.calculate() + + 1 ; + notUsedLocal--; + notUsedLocal += Integer.valueOf(1); + System.out.println(usedLocal); + } + System.out.println(usedLocal); + } + int calculate() { + return 0; + } + } + """) .doTest(); } @@ -258,12 +274,14 @@ public void unusedNative() { helper .addSourceLines( "UnusedNative.java", - "package unusedvars;", - "public class UnusedNative {", - " private int usedInNative1 = 0;", - " private String usedInNative2 = \"\";", - " private native void aNativeMethod();", - "}") + """ + package unusedvars; + public class UnusedNative { + private int usedInNative1 = 0; + private String usedInNative2 = ""; + private native void aNativeMethod(); + } + """) .doTest(); } @@ -272,25 +290,27 @@ public void unusedParamInPrivateMethod() { helper .addSourceLines( "UnusedParamInPrivateMethod.java", - "package unusedvars;", - "public class UnusedParamInPrivateMethod {", - " // BUG: Diagnostic contains: 'j' is never read", - " private void test(int i, int j) {", - " System.out.println(i);", - " }", - " private class Inner {", - " // BUG: Diagnostic contains: 'j' is never read", - " public void test(int i, int j) {", - " System.out.println(i);", - " }", - " }", - " private interface Foo {", - " void foo(int a);", - " }", - " public void main() {", - " test(1, 2);", - " }", - "}") + """ + package unusedvars; + public class UnusedParamInPrivateMethod { + // BUG: Diagnostic contains: 'j' is never read + private void test(int i, int j) { + System.out.println(i); + } + private class Inner { + // BUG: Diagnostic contains: 'j' is never read + public void test(int i, int j) { + System.out.println(i); + } + } + private interface Foo { + void foo(int a); + } + public void main() { + test(1, 2); + } + } + """) .doTest(); } @@ -299,103 +319,105 @@ public void unuseds() { helper .addSourceLines( "Unuseds.java", - "package unusedvars;", - "import java.io.IOException;", - "import java.io.ObjectStreamException;", - "import java.util.List;", - "import javax.inject.Inject;", - "public class Unuseds {", - " // BUG: Diagnostic contains:", - " private static final String NOT_USED_CONST_STR = \"unused_test\";", - " private static final String CONST_STR = \"test\";", - " // BUG: Diagnostic contains:", - " private int notUsed;", - " private List used;", - " public int publicOne;", - " private int[] ints;", - " @Inject", - " private int unusedExemptedByAnnotation;", - " @Inject", - " private void unusedMethodExemptedByAnnotation() {}", - " void test() {", - " this.notUsed = 0;", - " this.notUsed++;", - " this.notUsed += 0;", - " // BUG: Diagnostic contains:", - " int notUsedLocal;", - " notUsedLocal = 10;", - " int usedLocal = 0;", - " if (!used.get(usedLocal).toString().equals(CONST_STR)) {", - " used.add(\"test\");", - " }", - " // j is used", - " int j = 0;", - " used.get(j++);", - " ints[j--]++;", - " ints[1] = 0;", - " // Negative case (:( data flow analysis...).", - " byte[] notUsedLocalArray = new byte[]{};", - " notUsedLocalArray[0] += this.used.size();", - " char[] out = new char[]{};", - " for (int m = 0, n = 0; m < 1; m++) {", - " out[n++] = out[m];", - " }", - " // Negative case", - " double timestamp = 0.0;", - " set(timestamp += 1.0);", - " int valuesIndex1 = 0;", - " int valuesIndex2 = 0;", - " double[][][] values = null;", - " values[0][valuesIndex1][valuesIndex2] = 10;", - " System.out.println(values);", - " }", - " public void set(double d) {}", - " public void usedInMethodCall(double d) {", - " List notUseds = null;", - " int indexInMethodCall = 0;", - " // Must not be reported as unused", - " notUseds.get(indexInMethodCall).publicOne = 0;", - " }", - " void memberSelectUpdate1() {", - " List l = null;", - " // `u` should not be reported as unused.", - " Unuseds u = getFirst(l);", - " u.notUsed = 10;", - " System.out.println(l);", - " getFirst(l).notUsed = 100;", - " }", - " void memberSelectUpdate2() {", - " List l = null;", - " // `l` should not be reported as unused.", - " l.get(0).notUsed = 10;", - " }", - " Unuseds getFirst(List l) {", - " return l.get(0);", - " }", - " // Negative case. Must not report.", - " private int usedCount = 0;", - " int incCounter() {", - " return usedCount += 2;", - " }", - " // For testing the lack of NPE on return statement.", - " public void returnNothing() {", - " return;", - " }", - " // Negative case. Must not report.", - " public void testUsedArray() {", - " ints[0] = 0;", - " ints[0]++;", - " ints[0]--;", - " ints[0] -= 0;", - " }", - " @SuppressWarnings({\"deprecation\", \"unused\"})", - " class UsesSuppressWarning {", - " private int f1;", - " private void test1() {", - " int local;", - " }", - " }", - "}") + """ + package unusedvars; + import java.io.IOException; + import java.io.ObjectStreamException; + import java.util.List; + import javax.inject.Inject; + public class Unuseds { + // BUG: Diagnostic contains: + private static final String NOT_USED_CONST_STR = "unused_test"; + private static final String CONST_STR = "test"; + // BUG: Diagnostic contains: + private int notUsed; + private List used; + public int publicOne; + private int[] ints; + @Inject + private int unusedExemptedByAnnotation; + @Inject + private void unusedMethodExemptedByAnnotation() {} + void test() { + this.notUsed = 0; + this.notUsed++; + this.notUsed += 0; + // BUG: Diagnostic contains: + int notUsedLocal; + notUsedLocal = 10; + int usedLocal = 0; + if (!used.get(usedLocal).toString().equals(CONST_STR)) { + used.add("test"); + } + // j is used + int j = 0; + used.get(j++); + ints[j--]++; + ints[1] = 0; + // Negative case (:( data flow analysis...). + byte[] notUsedLocalArray = new byte[]{}; + notUsedLocalArray[0] += this.used.size(); + char[] out = new char[]{}; + for (int m = 0, n = 0; m < 1; m++) { + out[n++] = out[m]; + } + // Negative case + double timestamp = 0.0; + set(timestamp += 1.0); + int valuesIndex1 = 0; + int valuesIndex2 = 0; + double[][][] values = null; + values[0][valuesIndex1][valuesIndex2] = 10; + System.out.println(values); + } + public void set(double d) {} + public void usedInMethodCall(double d) { + List notUseds = null; + int indexInMethodCall = 0; + // Must not be reported as unused + notUseds.get(indexInMethodCall).publicOne = 0; + } + void memberSelectUpdate1() { + List l = null; + // `u` should not be reported as unused. + Unuseds u = getFirst(l); + u.notUsed = 10; + System.out.println(l); + getFirst(l).notUsed = 100; + } + void memberSelectUpdate2() { + List l = null; + // `l` should not be reported as unused. + l.get(0).notUsed = 10; + } + Unuseds getFirst(List l) { + return l.get(0); + } + // Negative case. Must not report. + private int usedCount = 0; + int incCounter() { + return usedCount += 2; + } + // For testing the lack of NPE on return statement. + public void returnNothing() { + return; + } + // Negative case. Must not report. + public void testUsedArray() { + ints[0] = 0; + ints[0]++; + ints[0]--; + ints[0] -= 0; + } + @SuppressWarnings({"deprecation", "unused"}) + class UsesSuppressWarning { + private int f1; + private void test1() { + int local; + } + } + } + """) .doTest(); } @@ -404,31 +426,35 @@ public void refactoring() { refactoringHelper .addInputLines( "Unuseds.java", - "package unusedvars;", - "public class Unuseds {", - " private static final String NOT_USED_CONST_STR = \"unused_test\";", - " private static final String CONST_STR = \"test\";", - " private int notUsed;", - " public int publicOne;", - " void test() {", - " this.notUsed = 0;", - " this.notUsed++;", - " this.notUsed += 0;", - " int notUsedLocal;", - " notUsedLocal = 10;", - " System.out.println(CONST_STR);", - " }", - "}") + """ + package unusedvars; + public class Unuseds { + private static final String NOT_USED_CONST_STR = "unused_test"; + private static final String CONST_STR = "test"; + private int notUsed; + public int publicOne; + void test() { + this.notUsed = 0; + this.notUsed++; + this.notUsed += 0; + int notUsedLocal; + notUsedLocal = 10; + System.out.println(CONST_STR); + } + } + """) .addOutputLines( "Unuseds.java", - "package unusedvars;", - "public class Unuseds {", - " private static final String CONST_STR = \"test\";", - " public int publicOne;", - " void test() {", - " System.out.println(CONST_STR);", - " }", - "}") + """ + package unusedvars; + public class Unuseds { + private static final String CONST_STR = "test"; + public int publicOne; + void test() { + System.out.println(CONST_STR); + } + } + """) .doTest(); } @@ -437,19 +463,21 @@ public void overridableMethods() { helper .addSourceLines( "Unuseds.java", - "package unusedvars;", - "public class Unuseds {", - " // BUG: Diagnostic contains: The parameter 'j' is never read", - " private int usedPrivateMethodWithUnusedParam(int i, int j) {", - " return i * 2;", - " }", - " int a = usedPrivateMethodWithUnusedParam(1, 2);", - " // In the following three cases, parameters should not be reported as unused,", - " // because methods are non-private.", - " public void publicMethodWithUnusedParam(int i, int j) {}", - " public void protectedMethodWithUnusedParam(int i, int j) {}", - " public void packageMethodWithUnusedParam(int i, int j) {}", - "}") + """ + package unusedvars; + public class Unuseds { + // BUG: Diagnostic contains: The parameter 'j' is never read + private int usedPrivateMethodWithUnusedParam(int i, int j) { + return i * 2; + } + int a = usedPrivateMethodWithUnusedParam(1, 2); + // In the following three cases, parameters should not be reported as unused, + // because methods are non-private. + public void publicMethodWithUnusedParam(int i, int j) {} + public void protectedMethodWithUnusedParam(int i, int j) {} + public void packageMethodWithUnusedParam(int i, int j) {} + } + """) .doTest(); } @@ -458,17 +486,19 @@ public void exemptedByName() { helper .addSourceLines( "Unuseds.java", - "package unusedvars;", - "class ExemptedByName {", - " private int unused;", - " private int unusedInt;", - " private static final int UNUSED_CONSTANT = 5;", - " private int ignored;", - " private int customUnused1;", - " private int customUnused2;", - " private int prefixUnused1Field;", - " private int prefixUnused2Field;", - "}") + """ + package unusedvars; + class ExemptedByName { + private int unused; + private int unusedInt; + private static final int UNUSED_CONSTANT = 5; + private int ignored; + private int customUnused1; + private int customUnused2; + private int prefixUnused1Field; + private int prefixUnused2Field; + } + """) .setArgs( "-XepOpt:Unused:exemptNames=customUnused1,customUnused2", "-XepOpt:Unused:exemptPrefixes=prefixunused1,prefixunused2") @@ -480,20 +510,22 @@ public void suppressions() { helper .addSourceLines( "Unuseds.java", - "package unusedvars;", - "class Suppressed {", - " @SuppressWarnings({\"deprecation\", \"unused\"})", - " class UsesSuppressWarning {", - " private int f1;", - " private void test1() {", - " int local;", - " }", - " @SuppressWarnings(value = \"unused\")", - " private void test2() {", - " int local;", - " }", - " }", - "}") + """ + package unusedvars; + class Suppressed { + @SuppressWarnings({"deprecation", "unused"}) + class UsesSuppressWarning { + private int f1; + private void test1() { + int local; + } + @SuppressWarnings(value = "unused") + private void test2() { + int local; + } + } + } + """) .doTest(); } @@ -502,13 +534,15 @@ public void unusedStaticField() { helper .addSourceLines( "UnusedStaticField.java", - "package unusedvars;", - "import java.util.ArrayList;", - "import java.util.List;", - "public class UnusedStaticField {", - " // BUG: Diagnostic contains: is never read", - " private static final List DATA = new ArrayList<>();", - "}") + """ + package unusedvars; + import java.util.ArrayList; + import java.util.List; + public class UnusedStaticField { + // BUG: Diagnostic contains: is never read + private static final List DATA = new ArrayList<>(); + } + """) .doTest(); } @@ -517,12 +551,14 @@ public void unusedStaticPrivate() { helper .addSourceLines( "UnusedStaticPrivate.java", - "package unusedvars;", - "public class UnusedStaticPrivate {", - " // BUG: Diagnostic contains: is never read", - " private static final String NOT_USED_CONST_STR = \"unused_test\";", - " static final String CONST_STR = \"test\";", - "}") + """ + package unusedvars; + public class UnusedStaticPrivate { + // BUG: Diagnostic contains: is never read + private static final String NOT_USED_CONST_STR = "unused_test"; + static final String CONST_STR = "test"; + } + """) .doTest(); } @@ -531,16 +567,18 @@ public void unusedTryResource() { helper .addSourceLines( "UnusedTryResource.java", - "package unusedvars;", - "public class UnusedTryResource {", - " public static void main(String[] args) {", - " try (A a = new A()) {", - " }", - " }", - "}", - "class A implements AutoCloseable {", - " public void close() {}", - "}") + """ + package unusedvars; + public class UnusedTryResource { + public static void main(String[] args) { + try (A a = new A()) { + } + } + } + class A implements AutoCloseable { + public void close() {} + } + """) .doTest(); } @@ -549,18 +587,22 @@ public void removal_javadocsAndNonJavadocs() { refactoringHelper .addInputLines( "UnusedWithComment.java", - "package unusedvars;", - "public class UnusedWithComment {", - " /**", - " * Comment for a field */", - " @SuppressWarnings(\"test\")", - " private Object field;", - "}") + """ + package unusedvars; + public class UnusedWithComment { + /** + * Comment for a field */ + @SuppressWarnings("test") + private Object field; + } + """) .addOutputLines( - "UnusedWithComment.java", // - "package unusedvars;", - "public class UnusedWithComment {", - "}") + "UnusedWithComment.java", + """ + package unusedvars; + public class UnusedWithComment { + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -569,16 +611,20 @@ public void removal_trailingComment() { refactoringHelper .addInputLines( "Test.java", - "public class Test {", - " public static final int A = 1; // foo", - "", - " private static final int B = 2;", - "}") + """ + public class Test { + public static final int A = 1; // foo + + private static final int B = 2; + } + """) .addOutputLines( - "Test.java", // - "public class Test {", - " public static final int A = 1; // foo", - "}") + "Test.java", + """ + public class Test { + public static final int A = 1; // foo + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -587,19 +633,23 @@ public void removal_javadocAndSingleLines() { refactoringHelper .addInputLines( "Test.java", - "public class Test {", - " public static final int A = 1; // foo", - "", - " /** Javadoc. */", - " // TODO: fix", - " // BUG: bug", - " private static final int B = 2;", - "}") + """ + public class Test { + public static final int A = 1; // foo + + /** Javadoc. */ + // TODO: fix + // BUG: bug + private static final int B = 2; + } + """) .addOutputLines( - "Test.java", // - "public class Test {", - " public static final int A = 1; // foo", - "}") + "Test.java", + """ + public class Test { + public static final int A = 1; // foo + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -608,15 +658,19 @@ public void removal_rogueBraces() { refactoringHelper .addInputLines( "Test.java", - "@SuppressWarnings(\"foo\" /* { */)", - "public class Test {", - " private static final int A = 1;", - "}") + """ + @SuppressWarnings("foo" /* { */) + public class Test { + private static final int A = 1; + } + """) .addOutputLines( - "Test.java", // - "@SuppressWarnings(\"foo\" /* { */)", - "public class Test {", - "}") + "Test.java", + """ + @SuppressWarnings("foo" /* { */) + public class Test { + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -625,13 +679,15 @@ public void unusedWithComment_interspersedComments() { helper .addSourceLines( "UnusedWithComment.java", - "package unusedvars;", - "public class UnusedWithComment {", - " private static final String foo = null, // foo", - " // BUG: Diagnostic contains:", - " bar = null;", - " public static String foo() { return foo; }", - "}") + """ + package unusedvars; + public class UnusedWithComment { + private static final String foo = null, // foo + // BUG: Diagnostic contains: + bar = null; + public static String foo() { return foo; } + } + """) .doTest(); } @@ -640,21 +696,23 @@ public void utf8Handling() { helper .addSourceLines( "Utf8Handling.java", - "package unusedvars;", - "public class Utf8Handling {", - " private int foo = 1;", - " public void test() {", - " System.out.println(\"広\");", - " for (int i = 0; i < 10; ++i) {", - " // BUG: Diagnostic contains: is never read", - " int notUsedLocal = calculate();", - " }", - " System.out.println(foo);", - " }", - " int calculate() {", - " return ++foo;", - " }", - "}") + """ + package unusedvars; + public class Utf8Handling { + private int foo = 1; + public void test() { + System.out.println("\u5e83"); + for (int i = 0; i < 10; ++i) { + // BUG: Diagnostic contains: is never read + int notUsedLocal = calculate(); + } + System.out.println(foo); + } + int calculate() { + return ++foo; + } + } + """) .doTest(); } @@ -663,13 +721,15 @@ public void methodAnnotationsExemptingParameters() { helper .addSourceLines( "A.java", - "package unusedvars;", - "class A {", - " { foo(1); }", - " @B", - " private static void foo(int a) {}", - "}", - "@interface B {}") + """ + package unusedvars; + class A { + { foo(1); } + @B + private static void foo(int a) {} + } + @interface B {} + """) .setArgs( ImmutableList.of("-XepOpt:Unused:methodAnnotationsExemptingParameters=unusedvars.B")) .doTest(); @@ -680,21 +740,23 @@ public void usedUnaryExpression() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "import java.util.Map;", - "import java.util.HashMap;", - "public class Test {", - " private int next = 1;", - " private Map xs = new HashMap<>();", - " public int frobnicate(String s) {", - " Integer x = xs.get(s);", - " if (x == null) {", - " x = next++;", - " xs.put(s, x);", - " }", - " return x;", - " }", - "}") + """ + package unusedvars; + import java.util.Map; + import java.util.HashMap; + public class Test { + private int next = 1; + private Map xs = new HashMap<>(); + public int frobnicate(String s) { + Integer x = xs.get(s); + if (x == null) { + x = next++; + xs.put(s, x); + } + return x; + } + } + """) .doTest(); } @@ -721,13 +783,15 @@ public void unusedInjectConstructorParameter() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "import javax.inject.Inject;", - "public class Test {", - " @Inject Test(", - " // BUG: Diagnostic contains:", - " String foo) {}", - "}") + """ + package unusedvars; + import javax.inject.Inject; + public class Test { + @Inject Test( + // BUG: Diagnostic contains: + String foo) {} + } + """) .doTest(); } @@ -736,16 +800,18 @@ public void unusedInjectMethodParameter() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "import com.google.inject.Provides;", - "class Test {", - " @Provides", - " public String test(", - " // BUG: Diagnostic contains:", - " String foo) {", - " return \"test\";", - " }", - "}") + """ + package unusedvars; + import com.google.inject.Provides; + class Test { + @Provides + public String test( + // BUG: Diagnostic contains: + String foo) { + return "test"; + } + } + """) .doTest(); } @@ -754,12 +820,14 @@ public void unusedInject_notByDefault() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "import javax.inject.Inject;", - "public class Test {", - " @Inject Object foo;", - " @Inject public Object bar;", - "}") + """ + package unusedvars; + import javax.inject.Inject; + public class Test { + @Inject Object foo; + @Inject public Object bar; + } + """) .doTest(); } @@ -768,22 +836,26 @@ public void variableKeepingSideEffects() { refactoringHelper .addInputLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "class Test {", - " private final ImmutableList foo = ImmutableList.of();", - " void test() {", - " ImmutableList foo = ImmutableList.of();", - " }", - "}") + """ + import com.google.common.collect.ImmutableList; + class Test { + private final ImmutableList foo = ImmutableList.of(); + void test() { + ImmutableList foo = ImmutableList.of(); + } + } + """) .addOutputLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "class Test {", - " { ImmutableList.of(); }", - " void test() {", - " ImmutableList.of();", - " }", - "}") + """ + import com.google.common.collect.ImmutableList; + class Test { + { ImmutableList.of(); } + void test() { + ImmutableList.of(); + } + } + """) .setFixChooser(FixChoosers.SECOND) .doTest(); } @@ -793,20 +865,24 @@ public void variableRemovingSideEffects() { refactoringHelper .addInputLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "class Test {", - " private final ImmutableList foo = ImmutableList.of();", - " void test() {", - " ImmutableList foo = ImmutableList.of();", - " }", - "}") + """ + import com.google.common.collect.ImmutableList; + class Test { + private final ImmutableList foo = ImmutableList.of(); + void test() { + ImmutableList foo = ImmutableList.of(); + } + } + """) .addOutputLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "class Test {", - " void test() {", - " }", - "}") + """ + import com.google.common.collect.ImmutableList; + class Test { + void test() { + } + } + """) .doTest(); } @@ -815,10 +891,12 @@ public void exemptedFieldsByType() { helper .addSourceLines( "Test.java", - "import org.junit.rules.TestRule;", - "class Test {", - " private TestRule rule;", - "}") + """ + import org.junit.rules.TestRule; + class Test { + private TestRule rule; + } + """) .doTest(); } @@ -827,17 +905,19 @@ public void findingBaseSymbol() { helper .addSourceLines( "Test.java", - "class Test {", - " int a;", - " void test() {", - " Test o = new Test();", - " ((Test) o).a = 1;", - " (((o))).a = 1;", - " Test p = new Test();", - " id(p).a = 1;", - " }", - " Test id(Test t) { return t; }", - "}") + """ + class Test { + int a; + void test() { + Test o = new Test(); + ((Test) o).a = 1; + (((o))).a = 1; + Test p = new Test(); + id(p).a = 1; + } + Test id(Test t) { return t; } + } + """) .doTest(); } @@ -846,21 +926,25 @@ public void fixPrivateMethod_usagesToo() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " int a = foo(1);", - " private int foo(int b) {", - " b = 1;", - " return 1;", - " }", - "}") + """ + class Test { + int a = foo(1); + private int foo(int b) { + b = 1; + return 1; + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " int a = foo();", - " private int foo() {", - " return 1;", - " }", - "}") + """ + class Test { + int a = foo(); + private int foo() { + return 1; + } + } + """) .doTest(); } @@ -869,20 +953,24 @@ public void fixPrivateMethod_parameterLocations() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " int a = foo(1, 2, 3) + bar(1, 2, 3) + baz(1, 2, 3);", - " private int foo(int a, int b, int c) { return a * b; }", - " private int bar(int a, int b, int c) { return b * c; }", - " private int baz(int a, int b, int c) { return a * c; }", - "}") + """ + class Test { + int a = foo(1, 2, 3) + bar(1, 2, 3) + baz(1, 2, 3); + private int foo(int a, int b, int c) { return a * b; } + private int bar(int a, int b, int c) { return b * c; } + private int baz(int a, int b, int c) { return a * c; } + } + """) .addOutputLines( "Test.java", - "class Test {", - " int a = foo(1, 2) + bar(2, 3) + baz(1, 3);", - " private int foo(int a, int b) { return a * b; }", - " private int bar(int b, int c) { return b * c; }", - " private int baz(int a, int c) { return a * c; }", - "}") + """ + class Test { + int a = foo(1, 2) + bar(2, 3) + baz(1, 3); + private int foo(int a, int b) { return a * b; } + private int bar(int b, int c) { return b * c; } + private int baz(int a, int c) { return a * c; } + } + """) .doTest(); } @@ -891,16 +979,20 @@ public void fixPrivateMethod_varArgs() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " int a = foo(1, 2, 3, 4);", - " private int foo(int a, int... b) { return a; }", - "}") + """ + class Test { + int a = foo(1, 2, 3, 4); + private int foo(int a, int... b) { return a; } + } + """) .addOutputLines( "Test.java", - "class Test {", - " int a = foo(1);", - " private int foo(int a) { return a; }", - "}") + """ + class Test { + int a = foo(1); + private int foo(int a) { return a; } + } + """) .doTest(); } @@ -909,16 +1001,20 @@ public void fixPrivateMethod_varArgs_noArgs() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " int a = foo(1);", - " private int foo(int a, int... b) { return a; }", - "}") + """ + class Test { + int a = foo(1); + private int foo(int a, int... b) { return a; } + } + """) .addOutputLines( "Test.java", - "class Test {", - " int a = foo(1);", - " private int foo(int a) { return a; }", - "}") + """ + class Test { + int a = foo(1); + private int foo(int a) { return a; } + } + """) .doTest(); } @@ -927,29 +1023,33 @@ public void fixPrivateMethod_varArgs_noArgs() { public void enumField() { refactoringHelper .addInputLines( - "Test.java", // - "enum Test {", - " ONE(\"1\", 1) {};", - " private String a;", - " private Test(String a, int x) {", - " this.a = a;", - " }", - " String a() {", - " return a;", - " }", - "}") + "Test.java", + """ + enum Test { + ONE("1", 1) {}; + private String a; + private Test(String a, int x) { + this.a = a; + } + String a() { + return a; + } + } + """) .addOutputLines( - "Test.java", // - "enum Test {", - " ONE(\"1\") {};", - " private String a;", - " private Test(String a) {", - " this.a = a;", - " }", - " String a() {", - " return a;", - " }", - "}") + "Test.java", + """ + enum Test { + ONE("1") {}; + private String a; + private Test(String a) { + this.a = a; + } + String a() { + return a; + } + } + """) .doTest(); } @@ -958,19 +1058,23 @@ public void enumField() { public void onlyEnumField() { refactoringHelper .addInputLines( - "Test.java", // - "enum Test {", - " ONE(1) {};", - " private Test(int x) {", - " }", - "}") + "Test.java", + """ + enum Test { + ONE(1) {}; + private Test(int x) { + } + } + """) .addOutputLines( - "Test.java", // - "enum Test {", - " ONE() {};", - " private Test() {", - " }", - "}") + "Test.java", + """ + enum Test { + ONE() {}; + private Test() { + } + } + """) .doTest(); } @@ -978,14 +1082,18 @@ public void onlyEnumField() { public void sideEffectFix() { refactoringHelper .addInputLines( - "Test.java", // - "class Test {", - " private static final int[] xs = new int[0];", - "}") + "Test.java", + """ + class Test { + private static final int[] xs = new int[0]; + } + """) .addOutputLines( - "Test.java", // - "class Test {", - "}") + "Test.java", + """ + class Test { + } + """) .doTest(); } @@ -993,22 +1101,26 @@ public void sideEffectFix() { public void sideEffectFieldFix() { refactoringHelper .addInputLines( - "Test.java", // - "class Test {", - " private int x = 1;", - " public int a() {", - " x = a();", - " return 1;", - " }", - "}") + "Test.java", + """ + class Test { + private int x = 1; + public int a() { + x = a(); + return 1; + } + } + """) .addOutputLines( - "Test.java", // - "class Test {", - " public int a() {", - " a();", - " return 1;", - " }", - "}") + "Test.java", + """ + class Test { + public int a() { + a(); + return 1; + } + } + """) .setFixChooser(FixChoosers.SECOND) .doTest(); } @@ -1017,21 +1129,25 @@ public void sideEffectFieldFix() { public void blockFixTest() { refactoringHelper .addInputLines( - "Test.java", // - "class Test {", - " void foo() {", - " int a = 1;", - " if (hashCode() > 0)", - " a = 2;", - " }", - "}") + "Test.java", + """ + class Test { + void foo() { + int a = 1; + if (hashCode() > 0) + a = 2; + } + } + """) .addOutputLines( - "Test.java", // - "class Test {", - " void foo() {", - " if (hashCode() > 0) {}", - " }", - "}") + "Test.java", + """ + class Test { + void foo() { + if (hashCode() > 0) {} + } + } + """) .doTest(); } @@ -1040,15 +1156,17 @@ public void unusedAssignment() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " Integer a = 1;", - " a.hashCode();", - " // BUG: Diagnostic contains: assignment to", - " a = 2;", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + Integer a = 1; + a.hashCode(); + // BUG: Diagnostic contains: assignment to + a = 2; + } + } + """) .doTest(); } @@ -1057,20 +1175,22 @@ public void unusedAssignment_messages() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public int test() {", - " // BUG: Diagnostic contains: This assignment to the local variable", - " int a = 1;", - " a = 2;", - " int b = a;", - " int c = b;", - " // BUG: Diagnostic contains: This assignment to the local variable", - " b = 2;", - " b = 3;", - " return b + c;", - " }", - "}") + """ + package unusedvars; + public class Test { + public int test() { + // BUG: Diagnostic contains: This assignment to the local variable + int a = 1; + a = 2; + int b = a; + int c = b; + // BUG: Diagnostic contains: This assignment to the local variable + b = 2; + b = 3; + return b + c; + } + } + """) .doTest(); } @@ -1079,14 +1199,16 @@ public void unusedAssignment_nulledOut_noWarning() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " Integer a = 1;", - " a.hashCode();", - " a = null;", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + Integer a = 1; + a.hashCode(); + a = null; + } + } + """) .doTest(); } @@ -1095,25 +1217,29 @@ public void unusedAssignment_nulledOut_thenAssignedAgain() { refactoringHelper .addInputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " Integer a = 1;", - " a.hashCode();", - " a = null;", - " a = 2;", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + Integer a = 1; + a.hashCode(); + a = null; + a = 2; + } + } + """) .addOutputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " Integer a = 1;", - " a.hashCode();", - " a = null;", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + Integer a = 1; + a.hashCode(); + a = null; + } + } + """) .doTest(); } @@ -1122,25 +1248,29 @@ public void unusedAssignment_initialAssignmentNull_givesWarning() { refactoringHelper .addInputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public String test() {", - " String a = null;", - " hashCode();", - " a = toString();", - " return a;", - " }", - "}") + """ + package unusedvars; + public class Test { + public String test() { + String a = null; + hashCode(); + a = toString(); + return a; + } + } + """) .addOutputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public String test() {", - " hashCode();", - " String a = toString();", - " return a;", - " }", - "}") + """ + package unusedvars; + public class Test { + public String test() { + hashCode(); + String a = toString(); + return a; + } + } + """) .doTest(); } @@ -1149,23 +1279,27 @@ public void unusedAssignmentAfterUse() { refactoringHelper .addInputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " int a = 1;", - " System.out.println(a);", - " a = 2;", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + int a = 1; + System.out.println(a); + a = 2; + } + } + """) .addOutputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " int a = 1;", - " System.out.println(a);", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + int a = 1; + System.out.println(a); + } + } + """) .doTest(); } @@ -1174,24 +1308,28 @@ public void unusedAssignmentWithFinalUse() { refactoringHelper .addInputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " int a = 1;", - " a = 2;", - " a = 3;", - " System.out.println(a);", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + int a = 1; + a = 2; + a = 3; + System.out.println(a); + } + } + """) .addOutputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " int a = 3;", - " System.out.println(a);", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + int a = 3; + System.out.println(a); + } + } + """) .doTest(); } @@ -1200,14 +1338,16 @@ public void assignmentUsedInExpression() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public int test() {", - " int a = 1;", - " a = a * 2;", - " return a;", - " }", - "}") + """ + package unusedvars; + public class Test { + public int test() { + int a = 1; + a = a * 2; + return a; + } + } + """) .doTest(); } @@ -1216,19 +1356,23 @@ public void assignmentToParameter() { refactoringHelper .addInputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test(int a) {", - " a = 2;", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test(int a) { + a = 2; + } + } + """) .addOutputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test(int a) {", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test(int a) { + } + } + """) .doTest(); } @@ -1237,13 +1381,15 @@ public void assignmentToParameter_thenUsed() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public int test(int a) {", - " a = 2;", - " return a;", - " }", - "}") + """ + package unusedvars; + public class Test { + public int test(int a) { + a = 2; + return a; + } + } + """) .doTest(); } @@ -1252,25 +1398,29 @@ public void assignmentToEnhancedForLoop() { refactoringHelper .addInputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test(Iterable as) {", - " for (int a : as) {", - " System.out.println(a);", - " a = 2;", - " }", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test(Iterable as) { + for (int a : as) { + System.out.println(a); + a = 2; + } + } + } + """) .addOutputLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test(Iterable as) {", - " for (int a : as) {", - " System.out.println(a);", - " }", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test(Iterable as) { + for (int a : as) { + System.out.println(a); + } + } + } + """) .doTest(); } @@ -1279,11 +1429,13 @@ public void assignmentWithinForLoop() { helper .addSourceLines( "Test.java", - "public class Test {", - " public void test() {", - " for (int a = 0; a < 10; a = a + 1) {}", - " }", - "}") + """ + public class Test { + public void test() { + for (int a = 0; a < 10; a = a + 1) {} + } + } + """) .doTest(); } @@ -1292,14 +1444,16 @@ public void assignmentSeparateFromDeclaration_noComplaint() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public void test() {", - " int a;", - " a = 1;", - " System.out.println(a);", - " }", - "}") + """ + package unusedvars; + public class Test { + public void test() { + int a; + a = 1; + System.out.println(a); + } + } + """) .doTest(); } @@ -1308,16 +1462,18 @@ public void unusedAssignment_negatives() { helper .addSourceLines( "Test.java", - "package unusedvars;", - "public class Test {", - " public int frobnicate() {", - " int a = 1;", - " if (hashCode() == 0) {", - " a = 2;", - " }", - " return a;", - " }", - "}") + """ + package unusedvars; + public class Test { + public int frobnicate() { + int a = 1; + if (hashCode() == 0) { + a = 2; + } + return a; + } + } + """) .doTest(); } @@ -1326,17 +1482,19 @@ public void exemptedMethods() { helper .addSourceLines( "Unuseds.java", - "package unusedvars;", - "import java.io.IOException;", - "import java.io.ObjectStreamException;", - "public class Unuseds implements java.io.Serializable {", - " private void readObject(java.io.ObjectInputStream in) throws IOException {}", - " private void writeObject(java.io.ObjectOutputStream out) throws IOException {}", - " private Object readResolve() {", - " return null;", - " }", - " private void readObjectNoData() throws ObjectStreamException {}", - "}") + """ + package unusedvars; + import java.io.IOException; + import java.io.ObjectStreamException; + public class Unuseds implements java.io.Serializable { + private void readObject(java.io.ObjectInputStream in) throws IOException {} + private void writeObject(java.io.ObjectOutputStream out) throws IOException {} + private Object readResolve() { + return null; + } + private void readObjectNoData() throws ObjectStreamException {} + } + """) .doTest(); } @@ -1345,29 +1503,31 @@ public void unusedReassignment_removeSideEffectsFix() { refactoringHelper .addInputLines( "Test.java", - "import java.util.ArrayList;", - "import java.util.Collection;", - "import java.util.List;", - "import static java.util.stream.Collectors.toList;", - "public class Test {", - " public void f(List> lists) {", - " List result =", - " lists.stream().collect(ArrayList::new, Collection::addAll," - + " Collection::addAll);", - " result = lists.stream().collect(ArrayList::new, ArrayList::addAll," - + " ArrayList::addAll);", - " }", - "}") + """ +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import static java.util.stream.Collectors.toList; +public class Test { + public void f(List> lists) { + List result = + lists.stream().collect(ArrayList::new, Collection::addAll, Collection::addAll); + result = lists.stream().collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll); + } +} +""") .addOutputLines( "Test.java", - "import java.util.ArrayList;", - "import java.util.Collection;", - "import java.util.List;", - "import static java.util.stream.Collectors.toList;", - "public class Test {", - " public void f(List> lists) {", - " }", - "}") + """ + import java.util.ArrayList; + import java.util.Collection; + import java.util.List; + import static java.util.stream.Collectors.toList; + public class Test { + public void f(List> lists) { + } + } + """) .setFixChooser(FixChoosers.FIRST) .doTest(); } @@ -1377,31 +1537,33 @@ public void unusedReassignment_keepSideEffectsFix() { refactoringHelper .addInputLines( "Test.java", - "import java.util.ArrayList;", - "import java.util.Collection;", - "import java.util.List;", - "import static java.util.stream.Collectors.toList;", - "public class Test {", - " public void f(List> lists) {", - " List result =", - " lists.stream().collect(ArrayList::new, Collection::addAll," - + " Collection::addAll);", - " result = lists.stream().collect(ArrayList::new, ArrayList::addAll," - + " ArrayList::addAll);", - " }", - "}") + """ +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import static java.util.stream.Collectors.toList; +public class Test { + public void f(List> lists) { + List result = + lists.stream().collect(ArrayList::new, Collection::addAll, Collection::addAll); + result = lists.stream().collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll); + } +} +""") .addOutputLines( "Test.java", - "import java.util.ArrayList;", - "import java.util.Collection;", - "import java.util.List;", - "import static java.util.stream.Collectors.toList;", - "public class Test {", - " public void f(List> lists) {", - " lists.stream().collect(ArrayList::new, Collection::addAll, Collection::addAll);", - " lists.stream().collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);", - " }", - "}") + """ + import java.util.ArrayList; + import java.util.Collection; + import java.util.List; + import static java.util.stream.Collectors.toList; + public class Test { + public void f(List> lists) { + lists.stream().collect(ArrayList::new, Collection::addAll, Collection::addAll); + lists.stream().collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll); + } + } + """) .setFixChooser(FixChoosers.SECOND) .doTest(); } @@ -1423,9 +1585,11 @@ public void nestedRecord() { helper .addSourceLines( "SimpleClass.java", - "public class SimpleClass {", - " public record SimpleRecord (Integer foo, Long bar) {}", - "}") + """ + public class SimpleClass { + public record SimpleRecord (Integer foo, Long bar) {} + } + """) .expectNoDiagnostics() .doTest(); } @@ -1436,22 +1600,24 @@ public void recordWithStaticFields() { helper .addSourceLines( "SimpleClass.java", - "public class SimpleClass {", - " public record MyRecord (int foo) {", - " private static int a = 1;", - " private static int b = 1;", - " // BUG: Diagnostic contains: is never read", - " private static int c = 1;", - " ", - " public MyRecord {", - " foo = Math.max(a, foo);", - " }", - " }", - "", - " public int b() {", - " return MyRecord.b;", - " }", - "}") + """ + public class SimpleClass { + public record MyRecord (int foo) { + private static int a = 1; + private static int b = 1; + // BUG: Diagnostic contains: is never read + private static int c = 1; + + public MyRecord { + foo = Math.max(a, foo); + } + } + + public int b() { + return MyRecord.b; + } + } + """) .doTest(); } @@ -1465,9 +1631,11 @@ public void nestedPrivateRecord() { helper .addSourceLines( "SimpleClass.java", - "public class SimpleClass {", - " private record SimpleRecord (Integer foo, Long bar) {}", - "}") + """ + public class SimpleClass { + private record SimpleRecord (Integer foo, Long bar) {} + } + """) .expectNoDiagnostics() .doTest(); } @@ -1496,14 +1664,16 @@ public void nestedPrivateRecordNormalCanonicalConstructor() { helper .addSourceLines( "SimpleClass.java", - "public class SimpleClass {", - " private record SimpleRecord (Integer foo, Long bar) {", - " private SimpleRecord(Integer foo, Long bar) {", - " this.foo = foo;", - " this.bar = bar;", - " }", - " }", - "}") + """ + public class SimpleClass { + private record SimpleRecord (Integer foo, Long bar) { + private SimpleRecord(Integer foo, Long bar) { + this.foo = foo; + this.bar = bar; + } + } + } + """) .expectNoDiagnostics() .doTest(); } @@ -1514,12 +1684,14 @@ public void unusedRecordConstructorParameter() { helper .addSourceLines( "SimpleRecord.java", - "public record SimpleRecord (int x) {", - " // BUG: Diagnostic contains: The parameter 'b' is never read", - " private SimpleRecord(int a, int b) {", - " this(a);", - " }", - "}") + """ + public record SimpleRecord (int x) { + // BUG: Diagnostic contains: The parameter 'b' is never read + private SimpleRecord(int a, int b) { + this(a); + } + } + """) .doTest(); } @@ -1529,14 +1701,16 @@ public void unusedInRecord() { helper .addSourceLines( "SimpleClass.java", - "public class SimpleClass {", - " public record SimpleRecord (Integer foo, Long bar) {", - " void f() {", - " // BUG: Diagnostic contains: is never read", - " int x = foo;", - " }", - " }", - "}") + """ + public class SimpleClass { + public record SimpleRecord (Integer foo, Long bar) { + void f() { + // BUG: Diagnostic contains: is never read + int x = foo; + } + } + } + """) .doTest(); } @@ -1545,22 +1719,26 @@ public void manyUnusedAssignments_terminalAssignmentBecomesVariable() { refactoringHelper .addInputLines( "Test.java", - "public class Test {", - " public void test () {", - " Integer a = 1;", - " a = 2;", - " a = 3;", - " a.hashCode();", - " }", - "}") + """ + public class Test { + public void test () { + Integer a = 1; + a = 2; + a = 3; + a.hashCode(); + } + } + """) .addOutputLines( "Test.java", - "public class Test {", - " public void test () {", - " Integer a = 3;", - " a.hashCode();", - " }", - "}") + """ + public class Test { + public void test () { + Integer a = 3; + a.hashCode(); + } + } + """) .doTest(); } @@ -1569,12 +1747,14 @@ public void unusedVariable_withinPrivateInnerClass() { helper .addSourceLines( "Test.java", - "class Test {", - " private class Inner {", - " // BUG: Diagnostic contains:", - " public int foo = 1;", - " }", - "}") + """ + class Test { + private class Inner { + // BUG: Diagnostic contains: + public int foo = 1; + } + } + """) .doTest(); } @@ -1585,10 +1765,12 @@ public void parcelableCreator_noFinding() { .addSourceFile("android/testdata/stubs/android/os/Parcelable.java") .addSourceLines( "Test.java", - "import android.os.Parcelable;", - "class Test {", - " private static final Parcelable.Creator CREATOR = null;", - "}") + """ + import android.os.Parcelable; + class Test { + private static final Parcelable.Creator CREATOR = null; + } + """) .doTest(); } @@ -1597,20 +1779,24 @@ public void nestedParameterRemoval() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " private int foo(int a, int b) { return b; }", - " void test() {", - " foo(foo(1, 2), 2);", - " }", - "}") + """ + class Test { + private int foo(int a, int b) { return b; } + void test() { + foo(foo(1, 2), 2); + } + } + """) .addOutputLines( "Test.java", - "class Test {", - " private int foo(int b) { return b; }", - " void test() {", - " foo(2);", - " }", - "}") + """ + class Test { + private int foo(int b) { return b; } + void test() { + foo(2); + } + } + """) .doTest(); } @@ -1619,21 +1805,23 @@ public void unusedFunctionalInterfaceParameter() { helper .addSourceLines( "Test.java", - "import java.util.Collections;", - "import java.util.Comparator;", - "import java.util.List;", - "class Test {", - " public void test(List xs) {", - " // BUG: Diagnostic contains: 'b' is never read", - " Collections.sort(xs, (a, b) -> a > a ? 1 : 0);", - " Collections.sort(xs, new Comparator() {", - " // BUG: Diagnostic contains: 'b' is never read", - " @Override public int compare(Integer a, Integer b) { return a; }", - " public void foo(int a, int b) {}", - " });", - " Collections.sort(xs, (a, unused) -> a > a ? 1 : 0);", - " }", - "}") + """ + import java.util.Collections; + import java.util.Comparator; + import java.util.List; + class Test { + public void test(List xs) { + // BUG: Diagnostic contains: 'b' is never read + Collections.sort(xs, (a, b) -> a > a ? 1 : 0); + Collections.sort(xs, new Comparator() { + // BUG: Diagnostic contains: 'b' is never read + @Override public int compare(Integer a, Integer b) { return a; } + public void foo(int a, int b) {} + }); + Collections.sort(xs, (a, unused) -> a > a ? 1 : 0); + } + } + """) .doTest(); } @@ -1642,17 +1830,19 @@ public void unusedWithinAnotherVariableTree() { helper .addSourceLines( "Test.java", - "import java.util.Collections;", - "import java.util.Comparator;", - "import java.util.List;", - "class Test {", - " public void test(List xs) {", - " var unusedLocal = ", - " xs.stream().sorted(", - " // BUG: Diagnostic contains: 'b' is never read", - " (a, b) -> a > a ? 1 : 0);", - " }", - "}") + """ + import java.util.Collections; + import java.util.Comparator; + import java.util.List; + class Test { + public void test(List xs) { + var unusedLocal = + xs.stream().sorted( + // BUG: Diagnostic contains: 'b' is never read + (a, b) -> a > a ? 1 : 0); + } + } + """) .doTest(); } @@ -1661,18 +1851,20 @@ public void unusedFunctionalInterfaceParameter_noFix() { refactoringHelper .addInputLines( "Test.java", - "import java.util.Collections;", - "import java.util.Comparator;", - "import java.util.List;", - "class Test {", - " public void test(List xs) {", - " Collections.sort(xs, (a, b) -> a > a ? 1 : 0);", - " Collections.sort(xs, (a, unused) -> a > a ? 1 : 0);", - " Collections.sort(xs, new Comparator() {", - " @Override public int compare(Integer a, Integer b) { return a; }", - " });", - " }", - "}") + """ + import java.util.Collections; + import java.util.Comparator; + import java.util.List; + class Test { + public void test(List xs) { + Collections.sort(xs, (a, b) -> a > a ? 1 : 0); + Collections.sort(xs, (a, unused) -> a > a ? 1 : 0); + Collections.sort(xs, new Comparator() { + @Override public int compare(Integer a, Integer b) { return a; } + }); + } + } + """) .expectUnchanged() .doTest(); } @@ -1682,21 +1874,23 @@ public void parameterUsedInOverride() { refactoringHelper .addInputLines( "App.java", - "public class App {", - " private static class Base {", - " protected void doStuff(String usedInDescendants) {}", - " }", - " private static class Descendant extends Base {", - " @Override", - " protected void doStuff(String actuallyUsed) {", - " System.out.println(actuallyUsed);", - " }", - " }", - " public static void main(String[] args) {", - " Base b = new Descendant();", - " b.doStuff(\"some string\");", - " }", - "}") + """ + public class App { + private static class Base { + protected void doStuff(String usedInDescendants) {} + } + private static class Descendant extends Base { + @Override + protected void doStuff(String actuallyUsed) { + System.out.println(actuallyUsed); + } + } + public static void main(String[] args) { + Base b = new Descendant(); + b.doStuff("some string"); + } + } + """) .expectUnchanged() .doTest(); } @@ -1707,11 +1901,13 @@ public void underscoreVariable() { refactoringHelper .addInputLines( "Test.java", - "class Test {", - " public static void main(String[] args) {", - " var _ = new Object();", - " }", - "}") + """ + class Test { + public static void main(String[] args) { + var _ = new Object(); + } + } + """) .expectUnchanged() .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/IsLoggableTagLengthTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/IsLoggableTagLengthTest.java index 64110ef1254..203d66d4bc2 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/IsLoggableTagLengthTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/android/IsLoggableTagLengthTest.java @@ -38,10 +38,12 @@ public void negativeCaseLiteral() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " public void log() { Log.isLoggable(\"SHORT_ENOUGH\", Log.INFO); }", - "}") + """ + import android.util.Log; + class Test { + public void log() { Log.isLoggable("SHORT_ENOUGH", Log.INFO); } + } + """) .doTest(); } @@ -50,11 +52,13 @@ public void positiveCaseLiteral() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " // BUG: Diagnostic contains: IsLoggableTagLength", - " public void log() { Log.isLoggable(\"THIS_TAG_NAME_IS_WAY_TOO_LONG\", Log.INFO); }", - "}") + """ + import android.util.Log; + class Test { + // BUG: Diagnostic contains: IsLoggableTagLength + public void log() { Log.isLoggable("THIS_TAG_NAME_IS_WAY_TOO_LONG", Log.INFO); } + } + """) .doTest(); } @@ -63,10 +67,12 @@ public void negativeCaseLiteralUnicode() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " public void log() { Log.isLoggable(\"🚀🚀🚀🚀\", Log.INFO); }", - "}") + """ +import android.util.Log; +class Test { + public void log() { Log.isLoggable("\ud83d\ude80\ud83d\ude80\ud83d\ude80\ud83d\ude80", Log.INFO); } +} +""") .doTest(); } @@ -75,11 +81,13 @@ public void positiveCaseLiteralUnicode() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " // BUG: Diagnostic contains: IsLoggableTagLength", - " public void log() { Log.isLoggable(\"☔☔☔☔☔☔☔☔☔☔☔☔\", Log.INFO); }", - "}") + """ +import android.util.Log; +class Test { + // BUG: Diagnostic contains: IsLoggableTagLength + public void log() { Log.isLoggable("\u2614\u2614\u2614\u2614\u2614\u2614\u2614\u2614\u2614\u2614\u2614\u2614", Log.INFO); } +} +""") .doTest(); } @@ -88,11 +96,13 @@ public void negativeCaseFinalField() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " static final String TAG = \"SHORT_ENOUGH\";", - " public void log() { Log.isLoggable(TAG, Log.INFO); }", - "}") + """ + import android.util.Log; + class Test { + static final String TAG = "SHORT_ENOUGH"; + public void log() { Log.isLoggable(TAG, Log.INFO); } + } + """) .doTest(); } @@ -101,12 +111,14 @@ public void positiveCaseFinalField() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " static final String TAG = \"THIS_TAG_NAME_IS_WAY_TOO_LONG\";", - " // BUG: Diagnostic contains: IsLoggableTagLength", - " public void log() { Log.isLoggable(TAG, Log.INFO); }", - "}") + """ + import android.util.Log; + class Test { + static final String TAG = "THIS_TAG_NAME_IS_WAY_TOO_LONG"; + // BUG: Diagnostic contains: IsLoggableTagLength + public void log() { Log.isLoggable(TAG, Log.INFO); } + } + """) .doTest(); } @@ -115,10 +127,12 @@ public void negativeCaseClassName() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " public void log() { Log.isLoggable(Test.class.getSimpleName(), Log.INFO); }", - "}") + """ + import android.util.Log; + class Test { + public void log() { Log.isLoggable(Test.class.getSimpleName(), Log.INFO); } + } + """) .doTest(); } @@ -127,13 +141,15 @@ public void positiveCaseClassName() { compilationHelper .addSourceLines( "ThisClassNameIsWayTooLong.java", - "import android.util.Log;", - "class ThisClassNameIsWayTooLong {", - " public void log() {", - " // BUG: Diagnostic contains: IsLoggableTagLength", - " Log.isLoggable(ThisClassNameIsWayTooLong.class.getSimpleName(), Log.INFO);", - " }", - "}") + """ + import android.util.Log; + class ThisClassNameIsWayTooLong { + public void log() { + // BUG: Diagnostic contains: IsLoggableTagLength + Log.isLoggable(ThisClassNameIsWayTooLong.class.getSimpleName(), Log.INFO); + } + } + """) .doTest(); } @@ -142,13 +158,15 @@ public void negativeCaseFinalFieldClassName() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " static final String TAG = Test.class.getSimpleName();", - " public void log() {", - " Log.isLoggable(TAG, Log.INFO);", - " }", - "}") + """ + import android.util.Log; + class Test { + static final String TAG = Test.class.getSimpleName(); + public void log() { + Log.isLoggable(TAG, Log.INFO); + } + } + """) .doTest(); } @@ -157,14 +175,16 @@ public void positiveCaseFinalFieldClassName() { compilationHelper .addSourceLines( "ThisClassNameIsWayTooLong.java", - "import android.util.Log;", - "class ThisClassNameIsWayTooLong {", - " static final String TAG = ThisClassNameIsWayTooLong.class.getSimpleName();", - " public void log() {", - " // BUG: Diagnostic contains: IsLoggableTagLength", - " Log.isLoggable(TAG, Log.INFO);", - " }", - "}") + """ + import android.util.Log; + class ThisClassNameIsWayTooLong { + static final String TAG = ThisClassNameIsWayTooLong.class.getSimpleName(); + public void log() { + // BUG: Diagnostic contains: IsLoggableTagLength + Log.isLoggable(TAG, Log.INFO); + } + } + """) .doTest(); } @@ -173,11 +193,13 @@ public void negativeCaseNonFinalFieldUninitialized() { compilationHelper .addSourceLines( "Test.java", - "import android.util.Log;", - "class Test {", - " String unknownValue;", - " public void log() { Log.isLoggable(unknownValue, Log.INFO); }", - "}") + """ + import android.util.Log; + class Test { + String unknownValue; + public void log() { Log.isLoggable(unknownValue, Log.INFO); } + } + """) .doTest(); } @@ -186,13 +208,15 @@ public void negativeCaseNonFinalFieldClassNameTooLong() { compilationHelper .addSourceLines( "ThisClassNameIsWayTooLong.java", - "import android.util.Log;", - "class ThisClassNameIsWayTooLong {", - " String TAG = ThisClassNameIsWayTooLong.class.getSimpleName();", - " public void log() {", - " Log.isLoggable(TAG, Log.INFO);", - " }", - "}") + """ + import android.util.Log; + class ThisClassNameIsWayTooLong { + String TAG = ThisClassNameIsWayTooLong.class.getSimpleName(); + public void log() { + Log.isLoggable(TAG, Log.INFO); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/formatstring/FormatStringAnnotationCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/formatstring/FormatStringAnnotationCheckerTest.java index 760bb528d07..cbf580d2545 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/formatstring/FormatStringAnnotationCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/formatstring/FormatStringAnnotationCheckerTest.java @@ -33,19 +33,21 @@ public void matches_failsWithNonMatchingFormatArgs() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public static void log(@FormatString String s, Object... args) {}", - " @FormatMethod public static void callLog(@FormatString String s, Object arg,", - " Object arg2) {", - " // BUG: Diagnostic contains: The number of format arguments passed with an", - " log(s, \"test\");", - " // BUG: Diagnostic contains: The format argument types passed with an", - " log(s, \"test1\", \"test2\");", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public static void log(@FormatString String s, Object... args) {} + @FormatMethod public static void callLog(@FormatString String s, Object arg, + Object arg2) { + // BUG: Diagnostic contains: The number of format arguments passed with an + log(s, "test"); + // BUG: Diagnostic contains: The format argument types passed with an + log(s, "test1", "test2"); + } + } + """) .doTest(); } @@ -54,15 +56,17 @@ public void matches_succeedsWithMatchingFormatStringAndArgs() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public static void log(@FormatString String s, Object... args) {}", - " @FormatMethod public static void callLog(@FormatString String s, Object arg) {", - " log(s, arg);", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public static void log(@FormatString String s, Object... args) {} + @FormatMethod public static void callLog(@FormatString String s, Object arg) { + log(s, arg); + } + } + """) .doTest(); } @@ -71,15 +75,17 @@ public void matches_succeedsForMatchingFormatMethodWithImplicitFormatString() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public static void log(@FormatString String s, Object... args) {}", - " @FormatMethod public static void callLog(String s, Object arg) {", - " log(s, arg);", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public static void log(@FormatString String s, Object... args) {} + @FormatMethod public static void callLog(String s, Object arg) { + log(s, arg); + } + } + """) .doTest(); } @@ -88,16 +94,18 @@ public void matches_failsWithMismatchedFormatString() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public static void log(@FormatString String s, Object... args) {}", - " public static void callLog() {", - " // BUG: Diagnostic contains: extra format arguments: used 1, provided 2", - " log(\"%s\", new Object(), new Object());", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public static void log(@FormatString String s, Object... args) {} + public static void callLog() { + // BUG: Diagnostic contains: extra format arguments: used 1, provided 2 + log("%s", new Object(), new Object()); + } + } + """) .doTest(); } @@ -106,16 +114,18 @@ public void matches_succeedsForCompileTimeConstantFormatString() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public static void log(@FormatString String s, Object... args) {}", - " public static void callLog() {", - " final String formatString = \"%d\";", - " log(formatString, Integer.valueOf(0));", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public static void log(@FormatString String s, Object... args) {} + public static void callLog() { + final String formatString = "%d"; + log(formatString, Integer.valueOf(0)); + } + } + """) .doTest(); } @@ -124,19 +134,21 @@ public void matches_failsWhenExpressionGivenForFormatString() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "public class FormatStringTestCase {", - " @FormatMethod static void log(String s, Object... args) {}", - " public static String formatString() { return \"\";}", - " public static void callLog() {", - " String format = \"log: \";", - " // BUG: Diagnostic contains: Format strings must be either literals or", - " log(format + 3);", - " // BUG: Diagnostic contains: Format strings must be either literals or", - " log(formatString());", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + public class FormatStringTestCase { + @FormatMethod static void log(String s, Object... args) {} + public static String formatString() { return "";} + public static void callLog() { + String format = "log: "; + // BUG: Diagnostic contains: Format strings must be either literals or + log(format + 3); + // BUG: Diagnostic contains: Format strings must be either literals or + log(formatString()); + } + } + """) .doTest(); } @@ -145,19 +157,21 @@ public void matches_failsForInvalidMethodHeaders() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " // BUG: Diagnostic contains: A method cannot have more than one @FormatString", - " @FormatMethod void log1(@FormatString String s1, @FormatString String s2) {}", - " // BUG: Diagnostic contains: An @FormatMethod must contain at least one String", - " @FormatMethod void log2(Object o) {}", - " // BUG: Diagnostic contains: Only strings can be annotated @FormatString.", - " @FormatMethod void log3(@FormatString Object o) {}", - " // BUG: Diagnostic contains: A parameter can only be annotated @FormatString in a", - " void log4(@FormatString Object o) {}", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + // BUG: Diagnostic contains: A method cannot have more than one @FormatString + @FormatMethod void log1(@FormatString String s1, @FormatString String s2) {} + // BUG: Diagnostic contains: An @FormatMethod must contain at least one String + @FormatMethod void log2(Object o) {} + // BUG: Diagnostic contains: Only strings can be annotated @FormatString. + @FormatMethod void log3(@FormatString Object o) {} + // BUG: Diagnostic contains: A parameter can only be annotated @FormatString in a + void log4(@FormatString Object o) {} + } + """) .doTest(); } @@ -166,21 +180,23 @@ public void matches_failsForIncorrectStringParameterUsedWithImplicitFormatString compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public static void log(@FormatString String s, Object... args) {}", - " @FormatMethod public static void callLog1(String format, String s, Object arg) {", - " // BUG: Diagnostic contains: Format strings must be compile time constants or", - " log(s, arg);", - " }", - " @FormatMethod public static void callLog2(String s, @FormatString String format,", - " Object arg) {", - " // BUG: Diagnostic contains: Format strings must be compile time constants or", - " log(s, arg);", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public static void log(@FormatString String s, Object... args) {} + @FormatMethod public static void callLog1(String format, String s, Object arg) { + // BUG: Diagnostic contains: Format strings must be compile time constants or + log(s, arg); + } + @FormatMethod public static void callLog2(String s, @FormatString String format, + Object arg) { + // BUG: Diagnostic contains: Format strings must be compile time constants or + log(s, arg); + } + } + """) .doTest(); } @@ -261,16 +277,18 @@ public void matches_failsForBadCallToConstructor() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public FormatStringTestCase(String s, Object... args) {}", - " public static void createTestCase(String s, Object arg) {", - " // BUG: Diagnostic contains: Format strings must be compile time constants or", - " new FormatStringTestCase(s, arg);", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public FormatStringTestCase(String s, Object... args) {} + public static void createTestCase(String s, Object arg) { + // BUG: Diagnostic contains: Format strings must be compile time constants or + new FormatStringTestCase(s, arg); + } + } + """) .doTest(); } @@ -279,18 +297,20 @@ public void matches_succeedsForMockitoMatchers() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import static org.mockito.ArgumentMatchers.any;", - "import static org.mockito.ArgumentMatchers.eq;", - "import static org.mockito.Mockito.verify;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public void log(@FormatString String s, Object... args) {}", - " public void callLog(String s, Object... args) {", - " verify(this).log(any(String.class), eq(args));", - " }", - "}") + """ + package test; + import static org.mockito.ArgumentMatchers.any; + import static org.mockito.ArgumentMatchers.eq; + import static org.mockito.Mockito.verify; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public void log(@FormatString String s, Object... args) {} + public void callLog(String s, Object... args) { + verify(this).log(any(String.class), eq(args)); + } + } + """) .doTest(); } @@ -299,18 +319,20 @@ public void matches_succeedsForMockitoArgumentMatchers() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import static org.mockito.ArgumentMatchers.any;", - "import static org.mockito.ArgumentMatchers.eq;", - "import static org.mockito.Mockito.verify;", - "import com.google.errorprone.annotations.FormatMethod;", - "import com.google.errorprone.annotations.FormatString;", - "public class FormatStringTestCase {", - " @FormatMethod public void log(@FormatString String s, Object... args) {}", - " public void callLog(String s, Object... args) {", - " verify(this).log(any(String.class), eq(args));", - " }", - "}") + """ + package test; + import static org.mockito.ArgumentMatchers.any; + import static org.mockito.ArgumentMatchers.eq; + import static org.mockito.Mockito.verify; + import com.google.errorprone.annotations.FormatMethod; + import com.google.errorprone.annotations.FormatString; + public class FormatStringTestCase { + @FormatMethod public void log(@FormatString String s, Object... args) {} + public void callLog(String s, Object... args) { + verify(this).log(any(String.class), eq(args)); + } + } + """) .doTest(); } @@ -319,15 +341,17 @@ public void negative_noFormatString() { compilationHelper .addSourceLines( "test/FormatStringTestCase.java", - "package test;", - "import com.google.errorprone.annotations.FormatMethod;", - "public class FormatStringTestCase {", - " // BUG: Diagnostic contains: must contain at least one String parameter", - " @FormatMethod public static void log(int x, int y) {}", - " void test() { ", - " log(1, 2);", - " }", - "}") + """ + package test; + import com.google.errorprone.annotations.FormatMethod; + public class FormatStringTestCase { + // BUG: Diagnostic contains: must contain at least one String parameter + @FormatMethod public static void log(int x, int y) {} + void test() { + log(1, 2); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectOnConstructorOfAbstractClassTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectOnConstructorOfAbstractClassTest.java index e162c9b16fe..b9a46fe9b0f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectOnConstructorOfAbstractClassTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectOnConstructorOfAbstractClassTest.java @@ -35,11 +35,13 @@ public void positiveCase() { compilationHelper .addSourceLines( "Foo.java", - "import javax.inject.Inject;", - "abstract class Foo {", - " // BUG: Diagnostic contains: Foo() {}", - " @Inject Foo() {}", - "}") + """ + import javax.inject.Inject; + abstract class Foo { + // BUG: Diagnostic contains: Foo() {} + @Inject Foo() {} + } + """) .doTest(); } @@ -48,11 +50,13 @@ public void guiceConstructor() { compilationHelper .addSourceLines( "Foo.java", - "import com.google.inject.Inject;", - "abstract class Foo {", - " // BUG: Diagnostic contains: Foo() {}", - " @Inject Foo() {}", - "}") + """ + import com.google.inject.Inject; + abstract class Foo { + // BUG: Diagnostic contains: Foo() {} + @Inject Foo() {} + } + """) .doTest(); } @@ -61,13 +65,15 @@ public void abstractClassInConcreteClass() { compilationHelper .addSourceLines( "Foo.java", - "import javax.inject.Inject;", - "class Bar {", - " abstract static class Foo {", - " // BUG: Diagnostic contains: Foo() {}", - " @Inject Foo() {}", - " }", - "}") + """ + import javax.inject.Inject; + class Bar { + abstract static class Foo { + // BUG: Diagnostic contains: Foo() {} + @Inject Foo() {} + } + } + """) .doTest(); } @@ -75,11 +81,13 @@ public void abstractClassInConcreteClass() { public void negativeCase() { compilationHelper .addSourceLines( - "Foo.java", // - "import javax.inject.Inject;", - "class Foo {", - " @Inject Foo() {}", - "}") + "Foo.java", + """ + import javax.inject.Inject; + class Foo { + @Inject Foo() {} + } + """) .doTest(); } @@ -88,12 +96,14 @@ public void concreteClassInAbstractClass() { compilationHelper .addSourceLines( "Foo.java", - "import javax.inject.Inject;", - "abstract class Bar {", - " static class Foo {", - " @Inject Foo() {}", - " }", - "}") + """ + import javax.inject.Inject; + abstract class Bar { + static class Foo { + @Inject Foo() {} + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MisplacedScopeAnnotationsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MisplacedScopeAnnotationsTest.java index fd4917f1975..0b5f4f456fa 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MisplacedScopeAnnotationsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MisplacedScopeAnnotationsTest.java @@ -35,13 +35,15 @@ public void positiveCase_methodInjection() { compilationHelper .addSourceLines( "Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " // BUG: Diagnostic contains: @Inject void someMethod( String foo) {}", - " @Inject void someMethod(@Singleton String foo) {}", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + // BUG: Diagnostic contains: @Inject void someMethod( String foo) {} + @Inject void someMethod(@Singleton String foo) {} + } + """) .doTest(); } @@ -50,24 +52,28 @@ public void positiveCase_providerMethod() { refactoringHelper .addInputLines( "in/Foo.java", - "import com.google.inject.Provides;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Provides String provideString(@Singleton @Named(\"foo\") String foo) {", - " return foo;", - " }", - "}") + """ + import com.google.inject.Provides; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Provides String provideString(@Singleton @Named("foo") String foo) { + return foo; + } + } + """) .addOutputLines( "out/Foo.java", - "import com.google.inject.Provides;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Provides String provideString( @Named(\"foo\") String foo) {", - " return foo;", - " }", - "}") + """ + import com.google.inject.Provides; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Provides String provideString( @Named("foo") String foo) { + return foo; + } + } + """) .doTest(); } @@ -76,20 +82,24 @@ public void positiveCase_injectConstructor() { refactoringHelper .addInputLines( "in/Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Inject Foo(@Singleton @Named(\"bar\") String bar) {}", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Inject Foo(@Singleton @Named("bar") String bar) {} + } + """) .addOutputLines( "out/Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Inject Foo( @Named(\"bar\") String bar) {}", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Inject Foo( @Named("bar") String bar) {} + } + """) .doTest(); } @@ -98,20 +108,24 @@ public void positiveCase_injectConstructorMultipleAnnotations() { refactoringHelper .addInputLines( "in/Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Inject Foo(@Singleton String bar, Integer i, @Singleton Long c) {}", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Inject Foo(@Singleton String bar, Integer i, @Singleton Long c) {} + } + """) .addOutputLines( "out/Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Inject Foo( String bar, Integer i, Long c) {}", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Inject Foo( String bar, Integer i, Long c) {} + } + """) .doTest(); } @@ -120,20 +134,24 @@ public void positiveCase_fieldInjection() { refactoringHelper .addInputLines( "in/Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Inject @Singleton String foo;", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Inject @Singleton String foo; + } + """) .addOutputLines( "out/Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Inject String foo;", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Inject String foo; + } + """) .doTest(); } @@ -142,18 +160,20 @@ public void negativeCase_noScopeAnnotationOnInjectedParameters() { compilationHelper .addSourceLines( "Foo.java", - "import dagger.Provides;", - "import dagger.Module;", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "@Module", - "class Foo {", - " @Provides @Singleton @Named(\"bar\")", - " int something(@Named(\"bar\") Integer bar) {", - " return 42;", - " }", - "}") + """ + import dagger.Provides; + import dagger.Module; + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + @Module + class Foo { + @Provides @Singleton @Named("bar") + int something(@Named("bar") Integer bar) { + return 42; + } + } + """) .doTest(); } @@ -162,26 +182,28 @@ public void negativeCase_scopeAnnotationIsAlsoQualifier() { compilationHelper .addSourceLines( "Foo.java", - "import dagger.Provides;", - "import dagger.Module;", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Qualifier;", - "import javax.inject.Scope;", - "import java.lang.annotation.Retention;", - "import java.lang.annotation.RetentionPolicy;", - "@Module", - "class Foo {", - " @Qualifier", - " @Scope", - " @Retention(RetentionPolicy.RUNTIME)", - " @interface RequestScoped {}", - " ", - " @Provides", - " int something(@RequestScoped Integer bar) {", - " return 42;", - " }", - "}") + """ + import dagger.Provides; + import dagger.Module; + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Qualifier; + import javax.inject.Scope; + import java.lang.annotation.Retention; + import java.lang.annotation.RetentionPolicy; + @Module + class Foo { + @Qualifier + @Scope + @Retention(RetentionPolicy.RUNTIME) + @interface RequestScoped {} + + @Provides + int something(@RequestScoped Integer bar) { + return 42; + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/QualifierOrScopeOnInjectMethodTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/QualifierOrScopeOnInjectMethodTest.java index ed51b541802..733ee820c42 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/QualifierOrScopeOnInjectMethodTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/QualifierOrScopeOnInjectMethodTest.java @@ -38,12 +38,14 @@ public void positiveCase() { compilationHelper .addSourceLines( "Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "class Foo {", - " // BUG: Diagnostic contains: @Inject void someMethod() {}", - " @Inject @Named(\"bar\") void someMethod() {}", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + class Foo { + // BUG: Diagnostic contains: @Inject void someMethod() {} + @Inject @Named("bar") void someMethod() {} + } + """) .doTest(); } @@ -52,20 +54,24 @@ public void positiveCase_injectConstructor() { refactoringHelper .addInputLines( "in/Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "class Foo {", - " @Inject @Singleton @Named(\"bar\") Foo() {}", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + class Foo { + @Inject @Singleton @Named("bar") Foo() {} + } + """) .addOutputLines( "out/Foo.java", - "import javax.inject.Inject;", - "import javax.inject.Named;", - "import javax.inject.Singleton;", - "@Singleton class Foo {", - " @Inject Foo() {}", - "}") + """ + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; + @Singleton class Foo { + @Inject Foo() {} + } + """) .doTest(); } @@ -74,13 +80,15 @@ public void negativeNotInject() { compilationHelper .addSourceLines( "Foo.java", - "import dagger.Provides;", - "import dagger.Module;", - "import javax.inject.Named;", - "@Module", - "class Foo {", - " @Provides @Named(\"bar\") int something() { return 42; }", - "}") + """ + import dagger.Provides; + import dagger.Module; + import javax.inject.Named; + @Module + class Foo { + @Provides @Named("bar") int something() { return 42; } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inlineme/SuggesterTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inlineme/SuggesterTest.java index 1ad9cdf6dbd..c27a562365b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inlineme/SuggesterTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inlineme/SuggesterTest.java @@ -73,6 +73,7 @@ public void setDeadline(Duration deadline) { this.deadline = deadline; } } + """) .addOutputLines( "Client.java", @@ -97,6 +98,7 @@ public void setDeadline(Duration deadline) { this.deadline = deadline; } } + """) .doTest(); } @@ -117,6 +119,7 @@ public Duration fromMillis(long millis) { return Duration.ofMillis(millis); } } + """) .addOutputLines( "Client.java", @@ -133,6 +136,7 @@ public Duration fromMillis(long millis) { return Duration.ofMillis(millis); } } + """) .doTest(); } @@ -153,6 +157,7 @@ public int stringLength() { return STR.length(); } } + """) .addOutputLines( "Client.java", @@ -186,6 +191,7 @@ public int stringLength() { return Client.STR.length(); } } + """) .addOutputLines( "Client.java", @@ -203,6 +209,7 @@ public int stringLength() { return Client.STR.length(); } } + """) .doTest(); } @@ -219,6 +226,7 @@ public final class Client { @Deprecated protected Client() {} } + """) .expectUnchanged() .doTest(); @@ -240,6 +248,7 @@ public Duration getZero() { return Duration.ZERO; } } + """) .addOutputLines( "Client.java", @@ -256,6 +265,7 @@ public Duration getZero() { return Duration.ZERO; } } + """) .doTest(); } @@ -277,6 +287,7 @@ public Duration getElapsed() { return Duration.between(Instant.ofEpochMilli(42), Instant.now()); } } + """) .addOutputLines( "Client.java", @@ -296,6 +307,7 @@ public Duration getElapsed() { return Duration.between(Instant.ofEpochMilli(42), Instant.now()); } } + """) .doTest(); } @@ -319,6 +331,7 @@ public int hashCode() { }; } } + """) .expectUnchanged() .doTest(); @@ -341,6 +354,7 @@ public Optional silly(Optional input) { return input.map(Duration::ofMillis); } } + """) .addOutputLines( "Client.java", @@ -358,6 +372,7 @@ public Optional silly(Optional input) { return input.map(Duration::ofMillis); } } + """) .doTest(); } @@ -378,6 +393,7 @@ public Instant silly() { return new Instant(); } } + """) .addOutputLines( "Client.java", @@ -394,6 +410,7 @@ public Instant silly() { return new Instant(); } } + """) .doTest(); } @@ -414,6 +431,7 @@ public Instant[] silly() { return new Instant[42]; } } + """) .addOutputLines( "Client.java", @@ -430,6 +448,7 @@ public Instant[] silly() { return new Instant[42]; } } + """) .doTest(); } @@ -450,6 +469,7 @@ public NestedClass silly() { public static class NestedClass {} } + """) .addOutputLines( "Client.java", @@ -467,6 +487,7 @@ public NestedClass silly() { public static class NestedClass {} } + """) .doTest(); } @@ -485,6 +506,7 @@ public String getName() { return "kurt"; } } + """) .addOutputLines( "Client.java", @@ -500,6 +522,7 @@ public String getName() { return "kurt"; } } + """) .doTest(); } @@ -522,6 +545,7 @@ public String getName(String defaultValue) { return "test"; } } + """) .addOutputLines( "Client.java", @@ -541,6 +565,7 @@ public String getName(String defaultValue) { return "test"; } } + """) .doTest(); } @@ -563,6 +588,7 @@ public Duration getMyDuration() { return myDuration; } } + """) .expectUnchanged() .doTest(); @@ -586,6 +612,7 @@ public Duration getMyDuration() { return this.myDuration; } } + """) .expectUnchanged() .doTest(); @@ -609,6 +636,7 @@ public void setDuration(Duration duration) { this.duration = duration; } } + """) .expectUnchanged() .doTest(); @@ -631,6 +659,7 @@ public final Duration after() { return duration; } } + """) .expectUnchanged() .addInputLines( @@ -648,6 +677,7 @@ public final Duration before() { return after(); } } + """) .addOutputLines( "Client.java", @@ -666,6 +696,7 @@ public final Duration before() { return after(); } } + """) .doTest(); } @@ -688,6 +719,7 @@ public void setDuration(Object duration) { public void foo(Duration duration) {} } + """) .addOutputLines( "Client.java", @@ -706,6 +738,7 @@ public void setDuration(Object duration) { public void foo(Duration duration) {} } + """) .doTest(); } @@ -728,6 +761,7 @@ public boolean silly() { return myDuration.isZero(); } } + """) .expectUnchanged() .doTest(); @@ -751,6 +785,7 @@ private boolean privateDelegate() { return false; } } + """) .expectUnchanged() .doTest(); @@ -774,6 +809,7 @@ public String readLine(String path) throws IOException { } } } + """) .expectUnchanged() .doTest(); @@ -793,6 +829,7 @@ public void foo(String input) { } } } + """) .expectUnchanged() .doTest(); @@ -812,6 +849,7 @@ public String foo(String input) { } } } + """) .expectUnchanged() .doTest(); @@ -833,6 +871,7 @@ public Duration getDeadline(Duration deadline) { return (deadline.compareTo(Duration.ZERO) > 0 ? Duration.ofSeconds(42) : Duration.ZERO); } } + """) .addOutputLines( "Client.java", @@ -852,6 +891,7 @@ public Duration getDeadline(Duration deadline) { return (deadline.compareTo(Duration.ZERO) > 0 ? Duration.ofSeconds(42) : Duration.ZERO); } } + """) .doTest(); } @@ -876,6 +916,7 @@ public static Duration getDeadline2() { return Duration.ZERO; } } + """) .addOutputLines( "Client.java", @@ -896,6 +937,7 @@ public static Duration getDeadline2() { return Duration.ZERO; } } + """) .doTest(); } @@ -916,6 +958,7 @@ public static String myFormat(String template, String arg) { return format(template, arg); } } + """) .addOutputLines( "Client.java", @@ -932,6 +975,7 @@ public static String myFormat(String template, String arg) { return format(template, arg); } } + """) .doTest(); } @@ -953,6 +997,7 @@ public static List newArrayList() { return new ArrayList(); } } + """) .addOutputLines( "Client.java", @@ -970,6 +1015,7 @@ public static List newArrayList() { return new ArrayList(); } } + """) .doTest(); } @@ -988,6 +1034,7 @@ public int method() { return 42; } } + """) .addOutputLines( "Client.java", @@ -1003,6 +1050,7 @@ public final int method() { return 42; } } + """) .doTest(); } @@ -1021,6 +1069,7 @@ public default int method() { return 42; } } + """) .expectUnchanged() .doTest(); @@ -1044,6 +1093,7 @@ public Client() { public Client(int value) {} } + """) .addOutputLines( "Client.java", @@ -1061,6 +1111,7 @@ public Client() { public Client(int value) {} } + """) .doTest(); } @@ -1081,6 +1132,7 @@ public static Client create() { private Client() {} } + """) .expectUnchanged() .doTest(); @@ -1105,6 +1157,7 @@ public void before() { public void after() {} } + """) .expectUnchanged() .doTest(); @@ -1132,6 +1185,7 @@ public static int after(int value) { return value; } } + """) .addOutputLines( "Client.java", @@ -1154,6 +1208,7 @@ public static int after(int value) { return value; } } + """) .doTest(); } @@ -1182,6 +1237,7 @@ public Optional reflective(Optional input) { return input.map(Duration::ofMillis); } } + """) .expectUnchanged() .doTest(); @@ -1208,6 +1264,7 @@ public byte[] encrypt(byte[] plaintext) { return plaintext; } } + """) .addOutputLines( "KeymasterEncrypter.java", @@ -1230,6 +1287,7 @@ public byte[] encrypt(byte[] plaintext) { return plaintext; } } + """) .doTest(); } @@ -1255,6 +1313,7 @@ public byte[] decrypt(byte[] ciphertext) { return ciphertext; } } + """) .addOutputLines( "KeymasterCrypter.java", @@ -1285,14 +1344,16 @@ public void noInlineMeSuggestionWhenParameterNamesAreArgN() { refactoringTestHelper .addInputLines( "Client.java", - "public final class Client {", - " @Deprecated", - " public void before(int arg0, int arg1) {", - " after(arg0, arg1);", - " }", - " public void after(int arg0, int arg1) {", - " }", - "}") + """ + public final class Client { + @Deprecated + public void before(int arg0, int arg1) { + after(arg0, arg1); + } + public void after(int arg0, int arg1) { + } + } + """) .expectUnchanged() .doTest(); } @@ -1302,26 +1363,30 @@ public void inlineMeSuggestionWhenParameterNamesAreNotArgN() { refactoringTestHelper .addInputLines( "Client.java", - "public final class Client {", - " @Deprecated", - " public void before(int int0, int int1) {", - " after(int0, int1);", - " }", - " public void after(int int0, int int1) {", - " }", - "}") + """ + public final class Client { + @Deprecated + public void before(int int0, int int1) { + after(int0, int1); + } + public void after(int int0, int int1) { + } + } + """) .addOutputLines( "Client.java", - "import com.google.errorprone.annotations.InlineMe;", - "public final class Client {", - " @InlineMe(replacement = \"this.after(int0, int1)\")", - " @Deprecated", - " public void before(int int0, int int1) {", - " after(int0, int1);", - " }", - " public void after(int int0, int int1) {", - " }", - "}") + """ + import com.google.errorprone.annotations.InlineMe; + public final class Client { + @InlineMe(replacement = "this.after(int0, int1)") + @Deprecated + public void before(int int0, int int1) { + after(int0, int1); + } + public void after(int int0, int int1) { + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inlineme/ValidatorTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inlineme/ValidatorTest.java index 17d512d1981..810884f63ec 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inlineme/ValidatorTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inlineme/ValidatorTest.java @@ -50,6 +50,7 @@ public static Client create() { public Client() {} } + """) .doTest(); } @@ -73,6 +74,7 @@ public static Client create() { public Client() {} } + """) .doTest(); } @@ -95,6 +97,7 @@ public Duration[] someDurations(int size) { return new Duration[size]; } } + """) .doTest(); } @@ -117,6 +120,7 @@ public static Duration[] someDurations(int size) { return new Duration[size]; } } + """) .doTest(); } @@ -139,6 +143,7 @@ public void before(String string) { public void after(String string) {} } + """) .doTest(); } @@ -161,6 +166,7 @@ public void before(String name) { public void after(String name) {} } + """) .doTest(); } @@ -183,6 +189,7 @@ public void before(String name1, String name2) { public void after(String name1, String name2) {} } + """) .doTest(); } @@ -206,6 +213,7 @@ public void before(String string) { public void after(String string) {} } + """) .doTest(); } @@ -229,6 +237,7 @@ public void before(String string) { public void after(Supplier supplier) {} } + """) .doTest(); } @@ -273,6 +282,7 @@ public boolean after(boolean b) { return !b; } } + """) .doTest(); } @@ -300,6 +310,7 @@ public boolean b() { return false; } } + """) .doTest(); } @@ -322,6 +333,7 @@ public void before() { public void after(Function function) {} } + """) .doTest(); } @@ -344,6 +356,7 @@ public String before() { return str; } } + """) .doTest(); } @@ -365,6 +378,7 @@ public String before() { return str; } } + """) .doTest(); } @@ -389,6 +403,7 @@ private String privateMethod() { return null; } } + """) .doTest(); } @@ -412,6 +427,7 @@ public void before(String string) { public void after(Supplier supplier) {} } + """) .doTest(); } @@ -438,6 +454,7 @@ public ProfileTimer(String name) { public ProfileTimer(Ticker ticker, String name) {} } + """) .doTest(); } @@ -461,6 +478,7 @@ public void setDeadlineInMillis(long millis) { public void setDeadline(Duration deadline) {} } + """) .expectErrorMessage( "BAR", @@ -487,6 +505,7 @@ public void setDeadlineInMillis(long millis) { public void setDeadline(java.time.Duration deadline) {} } + """) .doTest(); } @@ -508,6 +527,7 @@ public void before(long value) { public void after(String string) {} } + """) .doTest(); } @@ -529,6 +549,7 @@ public void before() { public void after(String string) {} } + """) .doTest(); } @@ -552,6 +573,7 @@ public void before() { } } } + """) .doTest(); } @@ -573,6 +595,7 @@ public void setDeadline(org.joda.time.Duration deadline) {} public void setDeadline(Duration deadline) {} } + """) .doTest(); } @@ -597,6 +620,7 @@ public void before() { public void after(Duration duration) {} } + """) .doTest(); } @@ -622,6 +646,7 @@ public void before() { public void after(Duration duration) {} } + """) .doTest(); } @@ -649,6 +674,7 @@ public static T after() { return (T) null; } } + """) .doTest(); } @@ -714,6 +740,7 @@ public static Duration parseDuration(String string) { } } } + """) .doTest(); } @@ -736,6 +763,7 @@ public void setName(String name) { this.name = name; } } + """) .doTest(); } @@ -757,6 +785,7 @@ public void setName(String name) { this.name = name; } } + """) .doTest(); } @@ -780,6 +809,7 @@ public static Client create() { return new Client(); } } + """) .doTest(); } @@ -803,6 +833,7 @@ public static Client create() { return new Client(); } } + """) .doTest(); } @@ -854,6 +885,7 @@ public void before(int... inputs) { public void after(int[] inputs) {} } + """) .doTest(); } @@ -874,6 +906,7 @@ public void noOp() { return; } } + """) .doTest(); } @@ -893,6 +926,7 @@ public final int multiply(int x, int y) { return x * y; } } + """) .doTest(); } @@ -912,6 +946,7 @@ public void customInlineMe() { String[] staticImports() default {}; } + """) .addSourceLines( "Client.java", @@ -934,17 +969,19 @@ public void validationFailsWhenParameterNamesAreArgN() { helper .addSourceLines( "Client.java", - "import com.google.errorprone.annotations.InlineMe;", - "public final class Client {", - " @Deprecated", - " @InlineMe(replacement = \"this.after(arg0, arg1)\")", - " // BUG: Diagnostic contains: `arg[0-9]+`", - " public void before(int arg0, int arg1) {", - " after(arg0, arg1);", - " }", - " public void after(int arg0, int arg1) {", - " }", - "}") + """ + import com.google.errorprone.annotations.InlineMe; + public final class Client { + @Deprecated + @InlineMe(replacement = "this.after(arg0, arg1)") + // BUG: Diagnostic contains: `arg[0-9]+` + public void before(int arg0, int arg1) { + after(arg0, arg1); + } + public void after(int arg0, int arg1) { + } + } + """) .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/EmptyBlockTagTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/EmptyBlockTagTest.java index 32a2709a3a0..5748b767b84 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/EmptyBlockTagTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/EmptyBlockTagTest.java @@ -35,19 +35,23 @@ public final class EmptyBlockTagTest { public void removes_emptyParam() { refactoring .addInputLines( - "Test.java", // - "interface Test {", - " /**", - " * @param p", - " */", - " void foo(int p);", - "}") + "Test.java", + """ + interface Test { + /** + * @param p + */ + void foo(int p); + } + """) .addOutputLines( - "Test.java", // - "interface Test {", - " /** */", - " void foo(int p);", - "}") + "Test.java", + """ + interface Test { + /** */ + void foo(int p); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -55,19 +59,23 @@ public void removes_emptyParam() { public void removes_emptyThrows() { refactoring .addInputLines( - "Test.java", // - "interface Test {", - " /**", - " * @throws Exception", - " */", - " void foo() throws Exception;", - "}") + "Test.java", + """ + interface Test { + /** + * @throws Exception + */ + void foo() throws Exception; + } + """) .addOutputLines( - "Test.java", // - "interface Test {", - " /** */", - " void foo() throws Exception;", - "}") + "Test.java", + """ + interface Test { + /** */ + void foo() throws Exception; + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -75,19 +83,23 @@ public void removes_emptyThrows() { public void removes_emptyReturn() { refactoring .addInputLines( - "Test.java", // - "interface Test {", - " /**", - " * @return", - " */", - " int foo();", - "}") + "Test.java", + """ + interface Test { + /** + * @return + */ + int foo(); + } + """) .addOutputLines( - "Test.java", // - "interface Test {", - " /** */", - " int foo();", - "}") + "Test.java", + """ + interface Test { + /** */ + int foo(); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -95,13 +107,15 @@ public void removes_emptyReturn() { public void removes_emptyDeprecated() { refactoring .addInputLines( - "Test.java", // - "interface Test {", - " /**", - " * @deprecated", - " */", - " int foo();", - "}") + "Test.java", + """ + interface Test { + /** + * @deprecated + */ + int foo(); + } + """) .expectUnchanged() .doTest(TestMode.TEXT_MATCH); } @@ -110,15 +124,17 @@ public void removes_emptyDeprecated() { public void removes_emptyDeprecatedOnClass() { compilationTestHelper .addSourceLines( - "Test.java", // - "/**", - " // BUG: Diagnostic contains:", - " * @deprecated", - " */", - "@Deprecated", - "interface Test {", - " void foo();", - "}") + "Test.java", + """ + /** + // BUG: Diagnostic contains: + * @deprecated + */ + @Deprecated + interface Test { + void foo(); + } + """) .doTest(); } @@ -126,19 +142,23 @@ public void removes_emptyDeprecatedOnClass() { public void removes_emptyParamOnClass() { refactoring .addInputLines( - "Test.java", // - "/**", - " * @param ", - " */", - "interface Test {", - " T foo();", - "}") + "Test.java", + """ + /** + * @param + */ + interface Test { + T foo(); + } + """) .addOutputLines( - "Test.java", // - "/** */", - "interface Test {", - " T foo();", - "}") + "Test.java", + """ + /** */ + interface Test { + T foo(); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -146,23 +166,27 @@ public void removes_emptyParamOnClass() { public void removes_emptyAllTheThings() { refactoring .addInputLines( - "Test.java", // - "interface Test {", - " /**", - " * @param p", - " * @return", - " * @throws Exception", - " */", - " @Deprecated", - " int foo(int p) throws Exception;", - "}") + "Test.java", + """ + interface Test { + /** + * @param p + * @return + * @throws Exception + */ + @Deprecated + int foo(int p) throws Exception; + } + """) .addOutputLines( - "Test.java", // - "interface Test {", - " /** */", - " @Deprecated", - " int foo(int p) throws Exception;", - "}") + "Test.java", + """ + interface Test { + /** */ + @Deprecated + int foo(int p) throws Exception; + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -170,13 +194,15 @@ public void removes_emptyAllTheThings() { public void keeps_paramWithDescription() { compilationTestHelper .addSourceLines( - "Test.java", // - "interface Test {", - " /**", - " * @param p is important", - " */", - " void foo(int p);", - "}") + "Test.java", + """ + interface Test { + /** + * @param p is important + */ + void foo(int p); + } + """) .doTest(); } @@ -184,13 +210,15 @@ public void keeps_paramWithDescription() { public void keeps_throwsWithDescription() { compilationTestHelper .addSourceLines( - "Test.java", // - "interface Test {", - " /**", - " * @throws Exception because blah", - " */", - " void foo() throws Exception;", - "}") + "Test.java", + """ + interface Test { + /** + * @throws Exception because blah + */ + void foo() throws Exception; + } + """) .doTest(); } @@ -198,13 +226,15 @@ public void keeps_throwsWithDescription() { public void keeps_returnWithDescription() { compilationTestHelper .addSourceLines( - "Test.java", // - "interface Test {", - " /**", - " * @return A value", - " */", - " int foo();", - "}") + "Test.java", + """ + interface Test { + /** + * @return A value + */ + int foo(); + } + """) .doTest(); } @@ -212,14 +242,16 @@ public void keeps_returnWithDescription() { public void keeps_deprecatedWithDescription() { compilationTestHelper .addSourceLines( - "Test.java", // - "interface Test {", - " /**", - " * @deprecated Very old", - " */", - " @Deprecated", - " void foo();", - "}") + "Test.java", + """ + interface Test { + /** + * @deprecated Very old + */ + @Deprecated + void foo(); + } + """) .doTest(); } @@ -227,17 +259,19 @@ public void keeps_deprecatedWithDescription() { public void keeps_allTheThingsWithDescriptions() { compilationTestHelper .addSourceLines( - "Test.java", // - "interface Test {", - " /**", - " * @param p is important", - " * @return a value", - " * @throws Exception because", - " * @deprecated Very old", - " */", - " @Deprecated", - " int foo(int p) throws Exception;", - "}") + "Test.java", + """ + interface Test { + /** + * @param p is important + * @return a value + * @throws Exception because + * @deprecated Very old + */ + @Deprecated + int foo(int p) throws Exception; + } + """) .doTest(); } @@ -245,14 +279,16 @@ public void keeps_allTheThingsWithDescriptions() { public void keeps_deprecatedOnClass() { compilationTestHelper .addSourceLines( - "Test.java", // - "/**", - " * @deprecated Use other Test2 instead", - " */", - "@Deprecated", - "interface Test {", - " void foo();", - "}") + "Test.java", + """ + /** + * @deprecated Use other Test2 instead + */ + @Deprecated + interface Test { + void foo(); + } + """) .doTest(); } @@ -260,13 +296,15 @@ public void keeps_deprecatedOnClass() { public void keeps_paramOnClass() { compilationTestHelper .addSourceLines( - "Test.java", // - "/**", - " * @param the input type param", - " */", - "interface Test {", - " T foo();", - "}") + "Test.java", + """ + /** + * @param the input type param + */ + interface Test { + T foo(); + } + """) .doTest(); } @@ -274,14 +312,16 @@ public void keeps_paramOnClass() { public void keeps_whenSuppressed() { compilationTestHelper .addSourceLines( - "Test.java", // - "interface Test {", - " /**", - " * @param p", - " */", - " @SuppressWarnings(\"EmptyBlockTag\")", - " void foo(int p);", - "}") + "Test.java", + """ + interface Test { + /** + * @param p + */ + @SuppressWarnings("EmptyBlockTag") + void foo(int p); + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/InvalidBlockTagTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/InvalidBlockTagTest.java index 11ee0bf534c..071ac0c92ba 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/InvalidBlockTagTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/InvalidBlockTagTest.java @@ -36,17 +36,21 @@ public final class InvalidBlockTagTest { public void typo() { refactoring .addInputLines( - "Test.java", // - "interface Test {", - " /** @return anything */", - " void foo();", - "}") + "Test.java", + """ + interface Test { + /** @return anything */ + void foo(); + } + """) .addOutputLines( - "Test.java", // - "interface Test {", - " /** @return anything */", - " void foo();", - "}") + "Test.java", + """ + interface Test { + /** @return anything */ + void foo(); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -54,11 +58,13 @@ public void typo() { public void veryBadTypo_noSuggestion() { refactoring .addInputLines( - "Test.java", // - "interface Test {", - " /** @returnFnargleBlargle anything */", - " void foo();", - "}") + "Test.java", + """ + interface Test { + /** @returnFnargleBlargle anything */ + void foo(); + } + """) .expectUnchanged() .doTest(TestMode.TEXT_MATCH); } @@ -67,11 +73,13 @@ public void veryBadTypo_noSuggestion() { public void otherAcceptedTags() { helper .addSourceLines( - "Test.java", // - "class Test {", - " /** @hide */", - " void test() {}", - "}") + "Test.java", + """ + class Test { + /** @hide */ + void test() {} + } + """) .doTest(); } @@ -80,36 +88,40 @@ public void inHtml() { refactoring .addInputLines( "Test.java", - "interface Test {", - " /**", - " * ", - " * @Override", - " * boolean equals(Object o);", - " * ", - " * @See Test", - " *
",
-            "   *    @Override",
-            "   *    boolean equals(Object o);",
-            "   *  
", - " */", - " void bar();", - "}") + """ + interface Test { + /** + * + * @Override + * boolean equals(Object o); + * + * @See Test + *
+               *    @Override
+               *    boolean equals(Object o);
+               *  
+ */ + void bar(); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /**", - " * ", - " * {@literal @}Override", - " * boolean equals(Object o);", - " * ", - " * @see Test", - " *
",
-            "   *    {@literal @}Override",
-            "   *    boolean equals(Object o);",
-            "   *  
", - " */", - " void bar();", - "}") + """ + interface Test { + /** + * + * {@literal @}Override + * boolean equals(Object o); + * + * @see Test + *
+               *    {@literal @}Override
+               *    boolean equals(Object o);
+               *  
+ */ + void bar(); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -118,20 +130,24 @@ public void parameterBlockTag() { refactoring .addInputLines( "Test.java", - "interface Test {", - " /**", - " * @a blah", - " */", - " void foo(int a);", - "}") + """ + interface Test { + /** + * @a blah + */ + void foo(int a); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /**", - " * @param a blah", - " */", - " void foo(int a);", - "}") + """ + interface Test { + /** + * @param a blah + */ + void foo(int a); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -140,13 +156,15 @@ public void parameterBlockTag_finding() { helper .addSourceLines( "Test.java", - "interface Test {", - " /**", - " // BUG: Diagnostic contains: {@code a}", - " * @a blah", - " */", - " void foo(int a);", - "}") + """ + interface Test { + /** + // BUG: Diagnostic contains: {@code a} + * @a blah + */ + void foo(int a); + } + """) .doTest(); } @@ -155,16 +173,20 @@ public void inheritDoc() { refactoring .addInputLines( "Test.java", - "interface Test {", - " /** @inheritDoc */", - " void frobnicate(String foo);", - "}") + """ + interface Test { + /** @inheritDoc */ + void frobnicate(String foo); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /** {@inheritDoc} */", - " void frobnicate(String foo);", - "}") + """ + interface Test { + /** {@inheritDoc} */ + void frobnicate(String foo); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -173,11 +195,13 @@ public void java8Tags() { helper .addSourceLines( "Test.java", - "/**", - " * @apiNote does nothing", - " * @implNote not implemented", - " */", - "class Test {}") + """ + /** + * @apiNote does nothing + * @implNote not implemented + */ + class Test {} + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/InvalidParamTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/InvalidParamTest.java index 31256a344e8..fa496abbf17 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/InvalidParamTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/InvalidParamTest.java @@ -39,15 +39,17 @@ public void badParameterName_positioning() { helper .addSourceLines( "Test.java", - "interface Test {", - " /**", - " * @param baz", - " // BUG: Diagnostic contains: Parameter name `c` is unknown", - " * @param c foo", - " * @param b bar", - " */", - " void foo(int a, int b);", - "}") + """ + interface Test { + /** + * @param baz + // BUG: Diagnostic contains: Parameter name `c` is unknown + * @param c foo + * @param b bar + */ + void foo(int a, int b); + } + """) .doTest(); } @@ -56,20 +58,24 @@ public void badColon() { refactoring .addInputLines( "Test.java", - "interface Test {", - " /**", - " * @param c: foo", - " */", - " void foo(int c);", - "}") + """ + interface Test { + /** + * @param c: foo + */ + void foo(int c); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /**", - " * @param c foo", - " */", - " void foo(int c);", - "}") + """ + interface Test { + /** + * @param c foo + */ + void foo(int c); + } + """) .doTest(TEXT_MATCH); } @@ -78,24 +84,28 @@ public void badParameterName() { refactoring .addInputLines( "Test.java", - "interface Test {", - " /**", - " * @param baz", - " * @param c foo", - " * @param b bar", - " */", - " void foo(int a, int b);", - "}") + """ + interface Test { + /** + * @param baz + * @param c foo + * @param b bar + */ + void foo(int a, int b); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /**", - " * @param baz", - " * @param a foo", - " * @param b bar", - " */", - " void foo(int a, int b);", - "}") + """ + interface Test { + /** + * @param baz + * @param a foo + * @param b bar + */ + void foo(int a, int b); + } + """) .doTest(TEXT_MATCH); } @@ -104,22 +114,26 @@ public void badTypeParameterName() { refactoring .addInputLines( "Test.java", - "interface Test {", - " /**", - " * @param baz", - " * @param a bar", - " */", - " void foo(int a);", - "}") + """ + interface Test { + /** + * @param baz + * @param a bar + */ + void foo(int a); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /**", - " * @param baz", - " * @param a bar", - " */", - " void foo(int a);", - "}") + """ + interface Test { + /** + * @param baz + * @param a bar + */ + void foo(int a); + } + """) .doTest(TEXT_MATCH); } @@ -128,20 +142,24 @@ public void verySimilarCodeParam() { refactoring .addInputLines( "Test.java", - "interface Test {", - " /**", - " * {@code foabar}, {@code barfoo}", - " */", - " void foo(int foobar);", - "}") + """ + interface Test { + /** + * {@code foabar}, {@code barfoo} + */ + void foo(int foobar); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /**", - " * {@code foobar}, {@code barfoo}", - " */", - " void foo(int foobar);", - "}") + """ + interface Test { + /** + * {@code foobar}, {@code barfoo} + */ + void foo(int foobar); + } + """) .doTest(TEXT_MATCH); } @@ -150,13 +168,15 @@ public void verySimilarCodeParam_diagnosticMessage() { helper .addSourceLines( "Test.java", - "interface Test {", - " /**", - " // BUG: Diagnostic contains: `foabar` is very close to the parameter `foobar`", - " * {@code foabar}, {@code barfoo}", - " */", - " void foo(int foobar);", - "}") + """ + interface Test { + /** + // BUG: Diagnostic contains: `foabar` is very close to the parameter `foobar` + * {@code foabar}, {@code barfoo} + */ + void foo(int foobar); + } + """) .doTest(); } @@ -165,15 +185,17 @@ public void negative() { helper .addSourceLines( "Test.java", - "interface Test {", - " /**", - " * Frobnicates a {@code foobarbaz}.", - " * @param baz", - " * @param a bar", - " * @param b quux", - " */", - " void foo(int a, int b, int foobarbaz);", - "}") + """ + interface Test { + /** + * Frobnicates a {@code foobarbaz}. + * @param baz + * @param a bar + * @param b quux + */ + void foo(int a, int b, int foobarbaz); + } + """) .doTest(); } @@ -182,10 +204,12 @@ public void excludedName_noMatchDespiteSimilarParam() { helper .addSourceLines( "Test.java", - "interface Test {", - " /** Returns {@code true}. */", - " boolean foo(int tree);", - "}") + """ + interface Test { + /** Returns {@code true}. */ + boolean foo(int tree); + } + """) .doTest(); } @@ -194,11 +218,13 @@ public void negative_record() { assume().that(Runtime.version().feature()).isAtLeast(16); helper .addSourceLines( - "Test.java", // - "/**", - " * @param name Name.", - " */", - "public record Test(String name) {}") + "Test.java", + """ + /** + * @param name Name. + */ + public record Test(String name) {} + """) .doTest(); } @@ -208,11 +234,13 @@ public void badParameterName_record() { helper .addSourceLines( "Test.java", - "/**", - " // BUG: Diagnostic contains: Parameter name `bar` is unknown", - " * @param bar Foo.", - " */", - "public record Test(String foo) {}") + """ + /** + // BUG: Diagnostic contains: Parameter name `bar` is unknown + * @param bar Foo. + */ + public record Test(String foo) {} + """) .doTest(); } @@ -222,23 +250,25 @@ public void multipleConstructors_record() { helper .addSourceLines( "Test.java", - "/**", - " * @param foo Foo.", - " * @param bar Bar.", - " */", - "public record Test(String foo, Integer bar) {", - " public Test(Integer bar) {", - " this(null, bar);", - " }", - "", - " /**", - " // BUG: Diagnostic contains: Parameter name `bar` is unknown", - " * @param bar Foo.", - " */", - " public Test(String foo) {", - " this(foo, null);", - " }", - "}") + """ + /** + * @param foo Foo. + * @param bar Bar. + */ + public record Test(String foo, Integer bar) { + public Test(Integer bar) { + this(null, bar); + } + + /** + // BUG: Diagnostic contains: Parameter name `bar` is unknown + * @param bar Foo. + */ + public Test(String foo) { + this(foo, null); + } + } + """) .doTest(); } @@ -248,21 +278,25 @@ public void typeParameter_record() { helper .addSourceLines( "Negative.java", - "/**", - " * @param The type parameter.", - " * @param contents Contents.", - " * @param bar Bar.", - " */", - "public record Negative(T contents, String bar) {}") + """ + /** + * @param The type parameter. + * @param contents Contents. + * @param bar Bar. + */ + public record Negative(T contents, String bar) {} + """) .addSourceLines( "Positive.java", - "/**", - " // BUG: Diagnostic contains: Parameter name `E` is unknown", - " * @param The type parameter.", - " * @param contents Contents.", - " * @param bar Bar.", - " */", - "public record Positive(T contents, String bar) {}") + """ + /** + // BUG: Diagnostic contains: Parameter name `E` is unknown + * @param The type parameter. + * @param contents Contents. + * @param bar Bar. + */ + public record Positive(T contents, String bar) {} + """) .doTest(); } @@ -272,12 +306,14 @@ public void compactConstructor_record() { helper .addSourceLines( "Test.java", - "/**", - " * @param name Name.", - " */", - "public record Test(String name) {", - " public Test {}", - "}") + """ + /** + * @param name Name. + */ + public record Test(String name) { + public Test {} + } + """) .doTest(); } @@ -287,18 +323,20 @@ public void normalConstructor_record() { helper .addSourceLines( "Test.java", - "/**", - " * @param name Name.", - " */", - "public record Test(String name) {", - " /**", - " // BUG: Diagnostic contains: Parameter name `foo` is unknown", - " * @param foo Name.", - " */", - " public Test(String name) {", - " this.name = name;", - " }", - " }") + """ + /** + * @param name Name. + */ + public record Test(String name) { + /** + // BUG: Diagnostic contains: Parameter name `foo` is unknown + * @param foo Name. + */ + public Test(String name) { + this.name = name; + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/MissingSummaryTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/MissingSummaryTest.java index 24bd71e829a..a7674711711 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/MissingSummaryTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/javadoc/MissingSummaryTest.java @@ -37,24 +37,28 @@ public final class MissingSummaryTest { public void replaceReturn() { refactoring .addInputLines( - "Test.java", // - "interface Test {", - " /**", - " * @param n foo", - " * @return n", - " */", - " int test(int n);", - "}") + "Test.java", + """ + interface Test { + /** + * @param n foo + * @return n + */ + int test(int n); + } + """) .addOutputLines( - "Test.java", // - "interface Test {", - " /**", - " * Returns n.", - " *", - " * @param n foo", - " */", - " int test(int n);", - "}") + "Test.java", + """ + interface Test { + /** + * Returns n. + * + * @param n foo + */ + int test(int n); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -63,34 +67,38 @@ public void replaceSee() { refactoring .addInputLines( "Test.java", - "interface Test {", - " /**", - " * @param n foo", - " * @see List other impl", - " */", - " void test(int n);", - " /**", - " * @param n foo", - " * @see List", - " */", - " void test2(int n);", - "}") + """ + interface Test { + /** + * @param n foo + * @see List other impl + */ + void test(int n); + /** + * @param n foo + * @see List + */ + void test2(int n); + } + """) .addOutputLines( "Test.java", - "interface Test {", - " /**", - " * See {@link List other impl}.", - " *", - " * @param n foo", - " */", - " void test(int n);", - " /**", - " * See {@link List}.", - " *", - " * @param n foo", - " */", - " void test2(int n);", - "}") + """ + interface Test { + /** + * See {@link List other impl}. + * + * @param n foo + */ + void test(int n); + /** + * See {@link List}. + * + * @param n foo + */ + void test2(int n); + } + """) .doTest(TestMode.TEXT_MATCH); } @@ -99,13 +107,15 @@ public void publicCase() { helper .addSourceLines( "Test.java", - "// BUG: Diagnostic contains: @see", - "/** @see another thing */", - "public interface Test {", - " // BUG: Diagnostic contains: @return", - " /** @return foo */", - " int test();", - "}") + """ + // BUG: Diagnostic contains: @see + /** @see another thing */ + public interface Test { + // BUG: Diagnostic contains: @return + /** @return foo */ + int test(); + } + """) .doTest(); } @@ -113,11 +123,13 @@ public void publicCase() { public void privateCase() { helper .addSourceLines( - "Test.java", // - "class Test {", - " /** @throws IllegalStateException */", - " private void test() {}", - "}") + "Test.java", + """ + class Test { + /** @throws IllegalStateException */ + private void test() {} + } + """) .doTest(); } @@ -125,13 +137,15 @@ public void privateCase() { public void effectivelyPrivateCase() { helper .addSourceLines( - "Test.java", // - "class Test {", - " private class Inner {", - " /** @throws IllegalStateException */", - " public void test() {}", - " }", - "}") + "Test.java", + """ + class Test { + private class Inner { + /** @throws IllegalStateException */ + public void test() {} + } + } + """) .doTest(); } @@ -140,14 +154,16 @@ public void negative() { helper .addSourceLines( "Test.java", - "interface Test {", - " /**", - " * Summary line!", - " *", - " * @return n", - " */", - " int test();", - "}") + """ + interface Test { + /** + * Summary line! + * + * @return n + */ + int test(); + } + """) .doTest(); } @@ -156,12 +172,14 @@ public void negativeAnnotations() { helper .addSourceLines( "Test.java", - "class Test {", - " /** @param o thing to compare */", - " @Override public boolean equals(Object o) { return true; }", - " /** @deprecated use something else */", - " @Deprecated public void frobnicate() {}", - "}") + """ + class Test { + /** @param o thing to compare */ + @Override public boolean equals(Object o) { return true; } + /** @deprecated use something else */ + @Deprecated public void frobnicate() {} + } + """) .doTest(); } @@ -170,10 +188,12 @@ public void negativeConstructor() { helper .addSourceLines( "Test.java", - "class Test {", - " /** @param o thing to compare */", - " public Test(Object o) {}", - "}") + """ + class Test { + /** @param o thing to compare */ + public Test(Object o) {} + } + """) .doTest(); } @@ -182,10 +202,12 @@ public void negativePrivate() { helper .addSourceLines( "Test.java", - "class Test {", - " /** @param o thing to compare */", - " private Test(Object o) {}", - "}") + """ + class Test { + /** @param o thing to compare */ + private Test(Object o) {} + } + """) .doTest(); } @@ -194,10 +216,12 @@ public void negativeOverride() { helper .addSourceLines( "Test.java", - "class Test implements java.util.function.Predicate {", - " /** @param o thing to compare */", - " public boolean test(Object o) { return false; }", - "}") + """ + class Test implements java.util.function.Predicate { + /** @param o thing to compare */ + public boolean test(Object o) { return false; } + } + """) .doTest(); } @@ -206,9 +230,11 @@ public void seeWithHtmlLink() { helper .addSourceLines( "Test.java", - "// BUG: Diagnostic contains:", - "/** @see bar */", - "public interface Test {}") + """ + // BUG: Diagnostic contains: + /** @see bar */ + public interface Test {} + """) .doTest(); } @@ -216,12 +242,14 @@ public void seeWithHtmlLink() { public void emptyReturn() { helper .addSourceLines( - "Test.java", // - "interface Test {", - " // BUG: Diagnostic contains:", - " /** @return */", - " int test(int n);", - "}") + "Test.java", + """ + interface Test { + // BUG: Diagnostic contains: + /** @return */ + int test(int n); + } + """) .doTest(); } @@ -229,12 +257,14 @@ public void emptyReturn() { public void emptyComment() { helper .addSourceLines( - "Test.java", // - "package test;", - "/** */", - "// BUG: Diagnostic contains: summary line is required", - "public class Test {", - "}") + "Test.java", + """ + package test; + /** */ + // BUG: Diagnostic contains: summary line is required + public class Test { + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/MultipleNullnessAnnotationsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/MultipleNullnessAnnotationsTest.java index c44d7e30bb8..1757669eb50 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/MultipleNullnessAnnotationsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/MultipleNullnessAnnotationsTest.java @@ -31,23 +31,25 @@ public void positive() { testHelper .addSourceLines( "Test.java", - "import org.checkerframework.checker.nullness.compatqual.NonNullDecl;", - "import org.checkerframework.checker.nullness.compatqual.NullableDecl;", - "import org.checkerframework.checker.nullness.qual.NonNull;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "import java.util.List;", - "abstract class Test {", - " // BUG: Diagnostic contains:", - " @Nullable @NonNull Object x;", - " // BUG: Diagnostic contains:", - " @NullableDecl static @NonNull Object y;", - " // BUG: Diagnostic contains:", - " List<@Nullable @NonNull String> z;", - " // BUG: Diagnostic contains:", - " @NullableDecl abstract @NonNull Object f();", - " // BUG: Diagnostic contains:", - " abstract void f(@NullableDecl Object @NonNull[] x);", - "}") + """ + import org.checkerframework.checker.nullness.compatqual.NonNullDecl; + import org.checkerframework.checker.nullness.compatqual.NullableDecl; + import org.checkerframework.checker.nullness.qual.NonNull; + import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; + abstract class Test { + // BUG: Diagnostic contains: + @Nullable @NonNull Object x; + // BUG: Diagnostic contains: + @NullableDecl static @NonNull Object y; + // BUG: Diagnostic contains: + List<@Nullable @NonNull String> z; + // BUG: Diagnostic contains: + @NullableDecl abstract @NonNull Object f(); + // BUG: Diagnostic contains: + abstract void f(@NullableDecl Object @NonNull[] x); + } + """) .doTest(); } @@ -56,15 +58,17 @@ public void negative() { testHelper .addSourceLines( "Test.java", - "import org.checkerframework.checker.nullness.compatqual.NonNullDecl;", - "import org.checkerframework.checker.nullness.compatqual.NullableDecl;", - "import org.checkerframework.checker.nullness.qual.NonNull;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "import java.util.List;", - "abstract class Test {", - " @NonNullDecl @NonNull Object x;", - " @NullableDecl static @Nullable Object y;", - "}") + """ + import org.checkerframework.checker.nullness.compatqual.NonNullDecl; + import org.checkerframework.checker.nullness.compatqual.NullableDecl; + import org.checkerframework.checker.nullness.qual.NonNull; + import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; + abstract class Test { + @NonNullDecl @NonNull Object x; + @NullableDecl static @Nullable Object y; + } + """) .doTest(); } @@ -73,12 +77,14 @@ public void disambiguation() { testHelper .addSourceLines( "Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "import java.util.List;", - "abstract class Test {", - " @Nullable Object @Nullable [] x;", - " abstract void f(@Nullable Object @Nullable ... x);", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; + abstract class Test { + @Nullable Object @Nullable [] x; + abstract void f(@Nullable Object @Nullable ... x); + } + """) .doTest(); } @@ -87,23 +93,27 @@ public void declarationAndType() { testHelper .addSourceLines( "Nullable.java", - "import java.lang.annotation.Target;", - "import java.lang.annotation.ElementType;", - "@Target({", - " ElementType.METHOD,", - " ElementType.FIELD,", - " ElementType.PARAMETER,", - " ElementType.LOCAL_VARIABLE,", - " ElementType.TYPE_USE", - "})", - "public @interface Nullable {}") + """ + import java.lang.annotation.Target; + import java.lang.annotation.ElementType; + @Target({ + ElementType.METHOD, + ElementType.FIELD, + ElementType.PARAMETER, + ElementType.LOCAL_VARIABLE, + ElementType.TYPE_USE + }) + public @interface Nullable {} + """) .addSourceLines( "Test.java", - "abstract class Test {", - " abstract void f(@Nullable Object x);", - " abstract @Nullable Object g();", - " @Nullable Object f;", - "}") + """ + abstract class Test { + abstract void f(@Nullable Object x); + abstract @Nullable Object g(); + @Nullable Object f; + } + """) .doTest(); } @@ -112,16 +122,18 @@ public void typeParameter() { testHelper .addSourceLines( "T.java", - "import org.checkerframework.checker.nullness.compatqual.NullableDecl;", - "import org.checkerframework.checker.nullness.qual.NonNull;", - "class T {", - " // BUG: Diagnostic contains:", - " @NullableDecl @NonNull X f;", - " // BUG: Diagnostic contains:", - " @NullableDecl @NonNull X g() {", - " return null;", - " }", - "}") + """ + import org.checkerframework.checker.nullness.compatqual.NullableDecl; + import org.checkerframework.checker.nullness.qual.NonNull; + class T { + // BUG: Diagnostic contains: + @NullableDecl @NonNull X f; + // BUG: Diagnostic contains: + @NullableDecl @NonNull X g() { + return null; + } + } + """) .doTest(); } @@ -130,12 +142,14 @@ public void arrayTypeAnnotation() { testHelper .addSourceLines( "T.java", - "import javax.annotation.CheckForNull;", - "import org.checkerframework.checker.nullness.qual.NonNull;", - "class T {", - " // BUG: Diagnostic contains:", - " @CheckForNull Object @NonNull [] f;", - "}") + """ + import javax.annotation.CheckForNull; + import org.checkerframework.checker.nullness.qual.NonNull; + class T { + // BUG: Diagnostic contains: + @CheckForNull Object @NonNull [] f; + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/NullablePrimitiveArrayTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/NullablePrimitiveArrayTest.java index 874966b940d..b125a35a2dc 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/NullablePrimitiveArrayTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/NullablePrimitiveArrayTest.java @@ -33,30 +33,34 @@ public void typeAnnotation() { testHelper .addInputLines( "Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "import org.checkerframework.checker.nullness.qual.NonNull;", - "abstract class Test {", - " @Nullable abstract byte[] f();", - " abstract @Nullable byte[] g();", - " abstract void h(@Nullable byte[] x);", - " abstract void i(@Nullable byte @Nullable [] x);", - " abstract void j(@Nullable byte... x);", - " abstract void k(@Nullable byte[][][] x);", - " abstract void l(@NonNull byte[] x);", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + import org.checkerframework.checker.nullness.qual.NonNull; + abstract class Test { + @Nullable abstract byte[] f(); + abstract @Nullable byte[] g(); + abstract void h(@Nullable byte[] x); + abstract void i(@Nullable byte @Nullable [] x); + abstract void j(@Nullable byte... x); + abstract void k(@Nullable byte[][][] x); + abstract void l(@NonNull byte[] x); + } + """) .addOutputLines( "Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "import org.checkerframework.checker.nullness.qual.NonNull;", - "abstract class Test {", - " abstract byte @Nullable [] f();", - " abstract byte @Nullable [] g();", - " abstract void h(byte @Nullable [] x);", - " abstract void i(byte @Nullable [] x);", - " abstract void j(byte @Nullable... x);", - " abstract void k(byte @Nullable [][][] x);", - " abstract void l(byte @NonNull [] x);", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + import org.checkerframework.checker.nullness.qual.NonNull; + abstract class Test { + abstract byte @Nullable [] f(); + abstract byte @Nullable [] g(); + abstract void h(byte @Nullable [] x); + abstract void i(byte @Nullable [] x); + abstract void j(byte @Nullable... x); + abstract void k(byte @Nullable [][][] x); + abstract void l(byte @NonNull [] x); + } + """) .doTest(BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH); } @@ -65,18 +69,22 @@ public void typeAnnotationWithOtherAnnotation() { testHelper .addInputLines( "Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "abstract class Test {", - " @SuppressWarnings(\"SomeOtherChecker\") // unrelated annotation", - " @Nullable abstract byte[] f();", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + abstract class Test { + @SuppressWarnings("SomeOtherChecker") // unrelated annotation + @Nullable abstract byte[] f(); + } + """) .addOutputLines( "Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "abstract class Test {", - " @SuppressWarnings(\"SomeOtherChecker\") // unrelated annotation", - " abstract byte @Nullable [] f();", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + abstract class Test { + @SuppressWarnings("SomeOtherChecker") // unrelated annotation + abstract byte @Nullable [] f(); + } + """) .doTest(BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH); } @@ -85,18 +93,22 @@ public void typeAnnotationWithOtherNullnessAnnotationDoesNotSuggestDoubleAnnotat testHelper .addInputLines( "Test.java", - "import javax.annotation.CheckForNull;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "abstract class Test {", - " @CheckForNull @Nullable abstract byte[] f();", - "}") + """ + import javax.annotation.CheckForNull; + import org.checkerframework.checker.nullness.qual.Nullable; + abstract class Test { + @CheckForNull @Nullable abstract byte[] f(); + } + """) .addOutputLines( "Test.java", - "import javax.annotation.CheckForNull;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "abstract class Test {", - " @CheckForNull abstract byte[] f();", - "}") + """ + import javax.annotation.CheckForNull; + import org.checkerframework.checker.nullness.qual.Nullable; + abstract class Test { + @CheckForNull abstract byte[] f(); + } + """) .doTest(BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH); } @@ -105,12 +117,14 @@ public void negative() { testHelper .addInputLines( "Test.java", - "import javax.annotation.Nullable;", - "abstract class Test {", - " @Nullable abstract Object[] f();", - " abstract @Nullable Object[] g();", - " abstract void h(@Nullable Object[] x);", - "}") + """ + import javax.annotation.Nullable; + abstract class Test { + @Nullable abstract Object[] f(); + abstract @Nullable Object[] g(); + abstract void h(@Nullable Object[] x); + } + """) .expectUnchanged() .doTest(); } @@ -120,18 +134,22 @@ public void alreadyAnnotatedForNullness() { testHelper .addInputLines( "Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "import org.checkerframework.checker.nullness.qual.NonNull;", - "abstract class Test {", - " abstract void f(@Nullable int @NonNull [] x);", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + import org.checkerframework.checker.nullness.qual.NonNull; + abstract class Test { + abstract void f(@Nullable int @NonNull [] x); + } + """) .addOutputLines( "Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "import org.checkerframework.checker.nullness.qual.NonNull;", - "abstract class Test {", - " abstract void f(int @NonNull [] x);", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + import org.checkerframework.checker.nullness.qual.NonNull; + abstract class Test { + abstract void f(int @NonNull [] x); + } + """) .doTest(); } @@ -140,12 +158,14 @@ public void declarationAnnotation() { testHelper .addInputLines( "Test.java", - "import javax.annotation.Nullable;", - "abstract class Test {", - " @Nullable abstract byte[] f();", - " abstract @Nullable byte[] g();", - " abstract void h(@Nullable byte[] x);", - "}") + """ + import javax.annotation.Nullable; + abstract class Test { + @Nullable abstract byte[] f(); + abstract @Nullable byte[] g(); + abstract void h(@Nullable byte[] x); + } + """) .expectUnchanged() .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/ReturnMissingNullableTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/ReturnMissingNullableTest.java index 95561d17158..e6296f36a95 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/ReturnMissingNullableTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/ReturnMissingNullableTest.java @@ -34,17 +34,19 @@ public void literalNullReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(boolean b) {", - " if (b) {", - " // BUG: Diagnostic contains: @Nullable", - " return null;", - " } else {", - " return \"negative\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(boolean b) { + if (b) { + // BUG: Diagnostic contains: @Nullable + return null; + } else { + return "negative"; + } + } + } + """) .doTest(); } @@ -53,17 +55,19 @@ public void parenthesizedLiteralNullReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(boolean b) {", - " if (b) {", - " // BUG: Diagnostic contains: @Nullable", - " return (null);", - " } else {", - " return \"negative\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(boolean b) { + if (b) { + // BUG: Diagnostic contains: @Nullable + return (null); + } else { + return "negative"; + } + } + } + """) .doTest(); } @@ -72,18 +76,20 @@ public void assignmentOfLiteralNullReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " String cachedMessage;", - " public String getMessage(boolean b) {", - " if (b) {", - " // BUG: Diagnostic contains: @Nullable", - " return cachedMessage = null;", - " } else {", - " return \"negative\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + String cachedMessage; + public String getMessage(boolean b) { + if (b) { + // BUG: Diagnostic contains: @Nullable + return cachedMessage = null; + } else { + return "negative"; + } + } + } + """) .doTest(); } @@ -92,17 +98,19 @@ public void castLiteralNullReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(boolean b) {", - " if (b) {", - " // BUG: Diagnostic contains: @Nullable", - " return (String) null;", - " } else {", - " return \"negative\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(boolean b) { + if (b) { + // BUG: Diagnostic contains: @Nullable + return (String) null; + } else { + return "negative"; + } + } + } + """) .doTest(); } @@ -111,13 +119,15 @@ public void conditionalLiteralNullReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(int x) {", - " // BUG: Diagnostic contains: @Nullable", - " return x >= 0 ? null : \"negative\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(int x) { + // BUG: Diagnostic contains: @Nullable + return x >= 0 ? null : "negative"; + } + } + """) .doTest(); } @@ -126,13 +136,15 @@ public void parenthesizedConditionalLiteralNullReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(int x) {", - " // BUG: Diagnostic contains: @Nullable", - " return (x >= 0 ? null : \"negative\");", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(int x) { + // BUG: Diagnostic contains: @Nullable + return (x >= 0 ? null : "negative"); + } + } + """) .doTest(); } @@ -143,16 +155,18 @@ public void switchExpressionTree() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(int x) {", - " // BUG: Diagnostic contains: @Nullable", - " return switch (x) {", - " case 0 -> null;", - " default -> \"non-zero\";", - " };", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(int x) { + // BUG: Diagnostic contains: @Nullable + return switch (x) { + case 0 -> null; + default -> "non-zero"; + }; + } + } + """) .doTest(); } @@ -163,15 +177,17 @@ public void switchExpressionTree_negative() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(int x) {", - " return switch (x) {", - " case 0 -> \"zero\";", - " default -> \"non-zero\";", - " };", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(int x) { + return switch (x) { + case 0 -> "zero"; + default -> "non-zero"; + }; + } + } + """) .doTest(); } @@ -180,18 +196,20 @@ public void switchStatement() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(int x) {", - " switch (x) {", - " case 0:", - " // BUG: Diagnostic contains: @Nullable", - " return null;", - " default:", - " return \"non-zero\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(int x) { + switch (x) { + case 0: + // BUG: Diagnostic contains: @Nullable + return null; + default: + return "non-zero"; + } + } + } + """) .doTest(); } @@ -200,17 +218,19 @@ public void switchStatement_negative() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage(int x) {", - " switch (x) {", - " case 0:", - " return \"zero\";", - " default:", - " return \"non-zero\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage(int x) { + switch (x) { + case 0: + return "zero"; + default: + return "non-zero"; + } + } + } + """) .doTest(); } @@ -219,14 +239,16 @@ public void voidReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object get() {", - " // BUG: Diagnostic contains: @Nullable", - " return getVoid();", - " }", - " abstract Void getVoid();", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object get() { + // BUG: Diagnostic contains: @Nullable + return getVoid(); + } + abstract Void getVoid(); + } + """) .doTest(); } @@ -235,16 +257,18 @@ public void subtypeOfVoidReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object get(Supplier s) {", - " // BUG: Diagnostic contains: @Nullable", - " return s.get();", - " }", - " interface Supplier {", - " T get();", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object get(Supplier s) { + // BUG: Diagnostic contains: @Nullable + return s.get(); + } + interface Supplier { + T get(); + } + } + """) .doTest(); } @@ -253,14 +277,16 @@ public void staticFinalFieldAboveUsage() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " static final Object NULL = null;", - " Object get() {", - " // BUG: Diagnostic contains: @Nullable", - " return NULL;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + static final Object NULL = null; + Object get() { + // BUG: Diagnostic contains: @Nullable + return NULL; + } + } + """) .doTest(); } @@ -269,14 +295,16 @@ public void staticFinalFieldBelowUsage() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object get() {", - " // BUG: Diagnostic contains: @Nullable", - " return NULL;", - " }", - " static final Object NULL = null;", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object get() { + // BUG: Diagnostic contains: @Nullable + return NULL; + } + static final Object NULL = null; + } + """) .doTest(); } @@ -285,14 +313,16 @@ public void instanceFinalField() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " final Object nullObject = null;", - " Object get() {", - " // BUG: Diagnostic contains: @Nullable", - " return nullObject;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + final Object nullObject = null; + Object get() { + // BUG: Diagnostic contains: @Nullable + return nullObject; + } + } + """) .doTest(); } @@ -301,14 +331,16 @@ public void memberSelectFinalField() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " final Object nullObject = null;", - " Object get() {", - " // BUG: Diagnostic contains: @Nullable", - " return this.nullObject;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + final Object nullObject = null; + Object get() { + // BUG: Diagnostic contains: @Nullable + return this.nullObject; + } + } + """) .doTest(); } @@ -317,22 +349,26 @@ public void multipleFilesFinalField() { createCompilationTestHelper() .addSourceLines( "Foo.java", - "class Foo {", - " final Object nullObject = null;", - " Object get() {", - " // BUG: Diagnostic contains: @Nullable", - " return nullObject;", - " }", - "}") + """ + class Foo { + final Object nullObject = null; + Object get() { + // BUG: Diagnostic contains: @Nullable + return nullObject; + } + } + """) .addSourceLines( "Bar.java", - "class Bar {", - " final Object nullObject = null;", - " Object get() {", - " // BUG: Diagnostic contains: @Nullable", - " return nullObject;", - " }", - "}") + """ + class Bar { + final Object nullObject = null; + Object get() { + // BUG: Diagnostic contains: @Nullable + return nullObject; + } + } + """) .doTest(); } @@ -341,14 +377,16 @@ public void voidField() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Void nullObject;", - " Object get() {", - " // BUG: Diagnostic contains: @Nullable", - " return nullObject;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Void nullObject; + Object get() { + // BUG: Diagnostic contains: @Nullable + return nullObject; + } + } + """) .doTest(); } @@ -357,22 +395,26 @@ public void typeAnnotatedArrayElement() { createRefactoringTestHelper() .addInputLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " @Nullable String[] getMessage(boolean b, String[] s) {", - " return b ? s : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + @Nullable String[] getMessage(boolean b, String[] s) { + return b ? s : null; + } + } + """) .addOutputLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " @Nullable String @Nullable [] getMessage(boolean b, String[] s) {", - " return b ? s : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + @Nullable String @Nullable [] getMessage(boolean b, String[] s) { + return b ? s : null; + } + } + """) .doTest(); } @@ -381,22 +423,26 @@ public void testTypeAnnotatedMultidimensionalArrayElement() { createRefactoringTestHelper() .addInputLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " String [] @Nullable [] getMessage(boolean b, String[][] s) {", - " return b ? s : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + String [] @Nullable [] getMessage(boolean b, String[][] s) { + return b ? s : null; + } + } + """) .addOutputLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " String @Nullable [] @Nullable [] getMessage(boolean b, String[][] s) {", - " return b ? s : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + String @Nullable [] @Nullable [] getMessage(boolean b, String[][] s) { + return b ? s : null; + } + } + """) .doTest(); } @@ -405,14 +451,16 @@ public void finalLocalVariable() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object get() {", - " final Object nullObject = null;", - " // BUG: Diagnostic contains: @Nullable", - " return nullObject;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object get() { + final Object nullObject = null; + // BUG: Diagnostic contains: @Nullable + return nullObject; + } + } + """) .doTest(); } @@ -421,14 +469,16 @@ public void effectivelyFinalLocalVariable() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object get() {", - " Object nullObject = null;", - " // BUG: Diagnostic contains: @Nullable", - " return nullObject;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object get() { + Object nullObject = null; + // BUG: Diagnostic contains: @Nullable + return nullObject; + } + } + """) .doTest(); } @@ -437,14 +487,16 @@ public void finalLocalVariableComplexTree() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object get(boolean b1, boolean b2, Object someObject) {", - " final Object nullObject = null;", - " // BUG: Diagnostic contains: @Nullable", - " return (b1 ? someObject : b2 ? nullObject : \"\");", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object get(boolean b1, boolean b2, Object someObject) { + final Object nullObject = null; + // BUG: Diagnostic contains: @Nullable + return (b1 ? someObject : b2 ? nullObject : ""); + } + } + """) .doTest(); } @@ -453,13 +505,15 @@ public void returnXIfXIsNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " // BUG: Diagnostic contains: @Nullable", - " return (o == null ? o : \"\");", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + // BUG: Diagnostic contains: @Nullable + return (o == null ? o : ""); + } + } + """) .doTest(); } @@ -468,13 +522,15 @@ public void returnXUnlessXIsXNotNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " // BUG: Diagnostic contains: @Nullable", - " return (o != null ? \"\" : o);", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + // BUG: Diagnostic contains: @Nullable + return (o != null ? "" : o); + } + } + """) .doTest(); } @@ -483,16 +539,18 @@ public void returnXInsideIfNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " if (o == null) {", - " // BUG: Diagnostic contains: @Nullable", - " return o;", - " }", - " return \"\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + if (o == null) { + // BUG: Diagnostic contains: @Nullable + return o; + } + return ""; + } + } + """) .doTest(); } @@ -501,17 +559,19 @@ public void returnXInsideElseOfNotNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " if (o != null) {", - " return \"\";", - " } else {", - " // BUG: Diagnostic contains: @Nullable", - " return o;", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + if (o != null) { + return ""; + } else { + // BUG: Diagnostic contains: @Nullable + return o; + } + } + } + """) .doTest(); } @@ -520,17 +580,19 @@ public void returnFieldInsideIfNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object o;", - " Object foo() {", - " if (o == null) {", - " // BUG: Diagnostic contains: @Nullable", - " return o;", - " }", - " return \"\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object o; + Object foo() { + if (o == null) { + // BUG: Diagnostic contains: @Nullable + return o; + } + return ""; + } + } + """) .doTest(); } @@ -539,15 +601,17 @@ public void otherVerify() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import static com.google.common.base.Verify.verify;", - "class LiteralNullReturnTest {", - " public String getMessage(boolean b) {", - " verify(b);", - " // BUG: Diagnostic contains: @Nullable", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import static com.google.common.base.Verify.verify; + class LiteralNullReturnTest { + public String getMessage(boolean b) { + verify(b); + // BUG: Diagnostic contains: @Nullable + return null; + } + } + """) .doTest(); } @@ -556,14 +620,16 @@ public void orNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import com.google.common.base.Optional;", - "class LiteralNullReturnTest {", - " public String getMessage(Optional m) {", - " // BUG: Diagnostic contains: @Nullable", - " return m.orNull();", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import com.google.common.base.Optional; + class LiteralNullReturnTest { + public String getMessage(Optional m) { + // BUG: Diagnostic contains: @Nullable + return m.orNull(); + } + } + """) .doTest(); } @@ -572,14 +638,16 @@ public void orElseNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import java.util.Optional;", - "class LiteralNullReturnTest {", - " public String getMessage(Optional m) {", - " // BUG: Diagnostic contains: @Nullable", - " return m.orElse(null);", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import java.util.Optional; + class LiteralNullReturnTest { + public String getMessage(Optional m) { + // BUG: Diagnostic contains: @Nullable + return m.orElse(null); + } + } + """) .doTest(); } @@ -588,13 +656,15 @@ public void implementsMapButAlwaysThrows() { createCompilationTestHelper() .addSourceLines( "MyMap.java", - "import java.util.Map;", - "abstract class MyMap implements Map {", - " @Override", - " public V put(K k, V v) {", - " throw new UnsupportedOperationException();", - " }", - "}") + """ + import java.util.Map; + abstract class MyMap implements Map { + @Override + public V put(K k, V v) { + throw new UnsupportedOperationException(); + } + } + """) .doTest(); } @@ -603,13 +673,15 @@ public void implementsMapButDoNotCall() { createCompilationTestHelper() .addSourceLines( "MyMap.java", - "import com.google.errorprone.annotations.DoNotCall;", - "import java.util.Map;", - "interface MyMap extends Map {", - " @DoNotCall", - " @Override", - " V put(K k, V v);", - "}") + """ + import com.google.errorprone.annotations.DoNotCall; + import java.util.Map; + interface MyMap extends Map { + @DoNotCall + @Override + V put(K k, V v); + } + """) .doTest(); } @@ -619,14 +691,16 @@ public void onlyIfAlreadyInScopeAndItIs() { .setArgs("-XepOpt:Nullness:OnlyIfAnnotationAlreadyInScope=true") .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " String getMessage(boolean b) {", - " // BUG: Diagnostic contains: @Nullable", - " return b ? \"\" : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + String getMessage(boolean b) { + // BUG: Diagnostic contains: @Nullable + return b ? "" : null; + } + } + """) .doTest(); } @@ -635,13 +709,15 @@ public void onlyStatementIsNullReturnButCannotBeOverridden() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public final class LiteralNullReturnTest {", - " public String getMessage() {", - " // BUG: Diagnostic contains: @Nullable", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public final class LiteralNullReturnTest { + public String getMessage() { + // BUG: Diagnostic contains: @Nullable + return null; + } + } + """) .doTest(); } @@ -650,22 +726,26 @@ public void arrayDeclaration() { createRefactoringTestHelper() .addInputLines( "in/com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "public class LiteralNullReturnTest {", - " public String[] getMessage(boolean b) {", - " return b ? null : new String[0];", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + public class LiteralNullReturnTest { + public String[] getMessage(boolean b) { + return b ? null : new String[0]; + } + } + """) .addOutputLines( "out/com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "public class LiteralNullReturnTest {", - " @Nullable public String[] getMessage(boolean b) {", - " return b ? null : new String[0];", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + public class LiteralNullReturnTest { + @Nullable public String[] getMessage(boolean b) { + return b ? null : new String[0]; + } + } + """) .doTest(); } @@ -674,22 +754,26 @@ public void arrayTypeUse() { createRefactoringTestHelper() .addInputLines( "in/com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " public String[] getMessage(boolean b) {", - " return b ? null : new String[0];", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + public String[] getMessage(boolean b) { + return b ? null : new String[0]; + } + } + """) .addOutputLines( "out/com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " public String @Nullable [] getMessage(boolean b) {", - " return b ? null : new String[0];", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + public String @Nullable [] getMessage(boolean b) { + return b ? null : new String[0]; + } + } + """) .doTest(); } @@ -698,22 +782,26 @@ public void arrayTypeUseTwoDimensional() { createRefactoringTestHelper() .addInputLines( "in/com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " public String[][] getMessage(boolean b, String[][] s) {", - " return b ? null : s;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + public String[][] getMessage(boolean b, String[][] s) { + return b ? null : s; + } + } + """) .addOutputLines( "out/com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " public String @Nullable [][] getMessage(boolean b, String[][] s) {", - " return b ? null : s;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + public String @Nullable [][] getMessage(boolean b, String[][] s) { + return b ? null : s; + } + } + """) .doTest(); } @@ -722,14 +810,16 @@ public void alreadyTypeAnnotatedInnerClassMemberSelect() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " class Inner {}", - " LiteralNullReturnTest.@Nullable Inner getMessage(boolean b, Inner i) {", - " return b ? i : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + class Inner {} + LiteralNullReturnTest.@Nullable Inner getMessage(boolean b, Inner i) { + return b ? i : null; + } + } + """) .doTest(); } @@ -738,14 +828,16 @@ public void alreadyTypeAnnotatedInnerClassNonMemberSelect() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " class Inner {}", - " @Nullable Inner getMessage(boolean b, Inner i) {", - " return b ? i : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + class Inner {} + @Nullable Inner getMessage(boolean b, Inner i) { + return b ? i : null; + } + } + """) .doTest(); } @@ -754,16 +846,18 @@ public void limitation_staticFinalFieldInitializedLater() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " static final Object NULL;", - " static {", - " NULL = null;", - " }", - " Object get() {", - " return NULL;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + static final Object NULL; + static { + NULL = null; + } + Object get() { + return NULL; + } + } + """) .doTest(); } @@ -790,14 +884,16 @@ public void limitation_finalLocalVariableInitializedLater() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object get() {", - " final Object nullObject;", - " nullObject = null;", - " return nullObject;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object get() { + final Object nullObject; + nullObject = null; + return nullObject; + } + } + """) .doTest(); } @@ -806,16 +902,18 @@ public void limitation_returnThisXInsideIfNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object o;", - " Object foo() {", - " if (this.o == null) {", - " return this.o;", - " }", - " return \"\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object o; + Object foo() { + if (this.o == null) { + return this.o; + } + return ""; + } + } + """) .doTest(); } @@ -825,31 +923,35 @@ public void removeSuppressWarnings_removeNullnessReturnWarning() { .setArgs("-XepOpt:Nullness:RemoveSuppressWarnings=true") .addInputLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " @SuppressWarnings(\"nullness:return\")", - " public String getMessage(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return \"negative\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + @SuppressWarnings("nullness:return") + public String getMessage(boolean b) { + if (b) { + return null; + } else { + return "negative"; + } + } + } + """) .addOutputLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.jspecify.annotations.Nullable;", - "public class LiteralNullReturnTest {", - "", - " public @Nullable String getMessage(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return \"negative\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.jspecify.annotations.Nullable; + public class LiteralNullReturnTest { + + public @Nullable String getMessage(boolean b) { + if (b) { + return null; + } else { + return "negative"; + } + } + } + """) .doTest(TEXT_MATCH); } @@ -858,12 +960,14 @@ public void negativeCases_onlyStatementIsNullReturn() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage() {", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage() { + return null; + } + } + """) .doTest(); } @@ -872,12 +976,14 @@ public void negativeCases_typeVariableUsage() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public T getMessage(boolean b, T t) {", - " return b ? null : t;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public T getMessage(boolean b, T t) { + return b ? null : t; + } + } + """) .doTest(); } @@ -886,14 +992,16 @@ public void negativeCases_alreadyAnnotated() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "public class LiteralNullReturnTest {", - " @Nullable", - " public String getMessage(boolean b) {", - " return b ? \"\" :null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + public class LiteralNullReturnTest { + @Nullable + public String getMessage(boolean b) { + return b ? "" :null; + } + } + """) .doTest(); } @@ -902,18 +1010,22 @@ public void negativeCases_alreadyAnnotatedNullableDecl() { createCompilationTestHelper() .addSourceLines( "com/google/anno/my/NullableDecl.java", - "package com.google.anno.my;", - "public @interface NullableDecl {}") + """ + package com.google.anno.my; + public @interface NullableDecl {} + """) .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import com.google.anno.my.NullableDecl;", - "public class LiteralNullReturnTest {", - " @NullableDecl", - " public String getMessage(boolean b) {", - " return b ? \"\" :null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import com.google.anno.my.NullableDecl; + public class LiteralNullReturnTest { + @NullableDecl + public String getMessage(boolean b) { + return b ? "" :null; + } + } + """) .doTest(); } @@ -922,13 +1034,15 @@ public void negativeCases_alreadyAnnotatedNullableType() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.compatqual.NullableType;", - "public class LiteralNullReturnTest {", - " public @NullableType String getMessage(boolean b) {", - " return b ? \"\" : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.compatqual.NullableType; + public class LiteralNullReturnTest { + public @NullableType String getMessage(boolean b) { + return b ? "" : null; + } + } + """) .doTest(); } @@ -937,19 +1051,23 @@ public void negativeCases_alreadyTypeAnnotated() { createCompilationTestHelper() .addSourceLines( "com/google/anno/my/Nullable.java", - "package com.google.anno.my;", - "import java.lang.annotation.ElementType;", - "import java.lang.annotation.Target;", - "@Target({ElementType.TYPE_USE})", - "public @interface Nullable {}") + """ + package com.google.anno.my; + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + @Target({ElementType.TYPE_USE}) + public @interface Nullable {} + """) .addSourceLines( "com/google/errorprone/bugpatterns/nullness/TypeAnnoReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class TypeAnnoReturnTest {", - " public @com.google.anno.my.Nullable String getMessage(boolean b) {", - " return b ? \"\" : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class TypeAnnoReturnTest { + public @com.google.anno.my.Nullable String getMessage(boolean b) { + return b ? "" : null; + } + } + """) .doTest(); } @@ -958,14 +1076,16 @@ public void negativeCases_alreadyDeclarationAnnotatedArray() { createAggressiveCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "public class LiteralNullReturnTest {", - " @Nullable", - " String[] getMessage(boolean b, String[] s) {", - " return b ? s : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + public class LiteralNullReturnTest { + @Nullable + String[] getMessage(boolean b, String[] s) { + return b ? s : null; + } + } + """) .doTest(); } @@ -974,13 +1094,15 @@ public void negativeCases_alreadyTypeAnnotatedArray() { createAggressiveCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " String @Nullable [] getMessage(boolean b, String[] s) {", - " return b ? s : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + String @Nullable [] getMessage(boolean b, String[] s) { + return b ? s : null; + } + } + """) .doTest(); } @@ -989,13 +1111,15 @@ public void negativeCases_alreadyTypeAnnotatedMemberSelect() { createAggressiveCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "public class LiteralNullReturnTest {", - " java.lang.@Nullable String getMessage(boolean b) {", - " return b ? \"\" : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.Nullable; + public class LiteralNullReturnTest { + java.lang.@Nullable String getMessage(boolean b) { + return b ? "" : null; + } + } + """) .doTest(); } @@ -1026,20 +1150,24 @@ public void negativeCases_nonNullArrayWithNullableElements() { createCompilationTestHelper() .addSourceLines( "com/google/anno/my/Nullable.java", - "package com.google.anno.my;", - "import java.lang.annotation.ElementType;", - "import java.lang.annotation.Target;", - "@Target({ElementType.TYPE_USE})", - "public @interface Nullable {}") + """ + package com.google.anno.my; + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + @Target({ElementType.TYPE_USE}) + public @interface Nullable {} + """) .addSourceLines( "com/google/errorprone/bugpatterns/nullness/NullableParameterTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import com.google.anno.my.Nullable;", - "public class NullableParameterTest {", - " public String[] apply(@Nullable String[] message) {", - " return message;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import com.google.anno.my.Nullable; + public class NullableParameterTest { + public String[] apply(@Nullable String[] message) { + return message; + } + } + """) .doTest(); } @@ -1048,12 +1176,14 @@ public void negativeCases_nonNullLiteral() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage() {", - " return \"hello\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage() { + return "hello"; + } + } + """) .doTest(); } @@ -1062,12 +1192,14 @@ public void negativeCases_nonNullMethod() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/NonNullMethodTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class NonNullMethodTest {", - " public String getMessage(int x) {", - " return String.valueOf(x);", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class NonNullMethodTest { + public String getMessage(int x) { + return String.valueOf(x); + } + } + """) .doTest(); } @@ -1076,13 +1208,15 @@ public void negativeCases_nonNullField() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/NonNullFieldTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class NonNullFieldTest {", - " private String message;", - " public String getMessage() {", - " return message;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class NonNullFieldTest { + private String message; + public String getMessage() { + return message; + } + } + """) .doTest(); } @@ -1091,12 +1225,14 @@ public void negativeCases_nonNullParameter() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/NonNullParameterTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class NonNullParameterTest {", - " public String apply(String message) {", - " return message;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class NonNullParameterTest { + public String apply(String message) { + return message; + } + } + """) .doTest(); } @@ -1105,14 +1241,16 @@ public void negativeCases_this() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/ThisTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class ThisTest {", - " private String message;", - " public ThisTest setMessage(String message) {", - " this.message = message;", - " return this;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class ThisTest { + private String message; + public ThisTest setMessage(String message) { + this.message = message; + return this; + } + } + """) .doTest(); } @@ -1121,17 +1259,19 @@ public void negativeCases_capturedLocal() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/CapturedLocalTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public abstract class CapturedLocalTest {", - " public abstract String getMessage();", - " public CapturedLocalTest withMessage(final String message) {", - " return new CapturedLocalTest() {", - " public String getMessage() {", - " return message;", - " }", - " };", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public abstract class CapturedLocalTest { + public abstract String getMessage(); + public CapturedLocalTest withMessage(final String message) { + return new CapturedLocalTest() { + public String getMessage() { + return message; + } + }; + } + } + """) .doTest(); } @@ -1144,12 +1284,14 @@ public void negativeCases_primitiveReturnType() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/PrimitiveReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class PrimitiveReturnTest {", - " public int getCount() {", - " return (Integer) null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class PrimitiveReturnTest { + public int getCount() { + return (Integer) null; + } + } + """) .doTest(); } @@ -1158,13 +1300,15 @@ public void negativeCases_voidMethod() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/VoidMethodTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class VoidMethodTest {", - " public void run(int iterations) {", - " if (iterations <= 0) { return; }", - " run(iterations - 1);", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class VoidMethodTest { + public void run(int iterations) { + if (iterations <= 0) { return; } + run(iterations - 1); + } + } + """) .doTest(); } @@ -1173,14 +1317,16 @@ public void negativeCases_voidTypedMethod() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/VoidTypeTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class VoidTypeTest {", - " public Void run(int iterations) {", - " if (iterations <= 0) { return null; }", - " run(iterations - 1);", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class VoidTypeTest { + public Void run(int iterations) { + if (iterations <= 0) { return null; } + run(iterations - 1); + return null; + } + } + """) .doTest(); } @@ -1189,12 +1335,14 @@ public void negativeCases_nullableReturnInLambda() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/MissingNullableReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "public class MissingNullableReturnTest {", - " public static final java.util.function.Function IDENTITY =", - " (s -> { return s != null ? s : null; });", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + public class MissingNullableReturnTest { + public static final java.util.function.Function IDENTITY = + (s -> { return s != null ? s : null; }); + } + """) .doTest(); } @@ -1203,13 +1351,15 @@ public void negativeCases_returnLambda() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/MissingNullableReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "public class MissingNullableReturnTest {", - " public static java.util.function.Function identity() {", - " return s -> s;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + public class MissingNullableReturnTest { + public static java.util.function.Function identity() { + return s -> s; + } + } + """) .doTest(); } @@ -1218,13 +1368,15 @@ public void negativeCases_returnParenthesizedLambda() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/MissingNullableReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "public class MissingNullableReturnTest {", - " public static java.util.function.Function identity() {", - " return (s -> s);", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + public class MissingNullableReturnTest { + public static java.util.function.Function identity() { + return (s -> s); + } + } + """) .doTest(); } @@ -1235,17 +1387,19 @@ public void negativeCases_mixedMethodFieldAccessPath() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/MissingNullableReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nonnull;", - "public class MissingNullableReturnTest {", - " public @Nonnull MyClass test() {", - " return ((MyClass) null).myMethod().myField;", - " }", - " abstract class MyClass {", - " abstract MyClass myMethod();", - " MyClass myField;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nonnull; + public class MissingNullableReturnTest { + public @Nonnull MyClass test() { + return ((MyClass) null).myMethod().myField; + } + abstract class MyClass { + abstract MyClass myMethod(); + MyClass myField; + } + } + """) .doTest(); } @@ -1255,17 +1409,19 @@ public void negativeCases_delegate() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/MissingNullableReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "import java.util.Optional;", - "public class MissingNullableReturnTest {", - " public String get() {", - " return getInternal(true, null);", - " }", - " private String getInternal(boolean flag, @Nullable Integer i) {", - " return \"hello\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + import java.util.Optional; + public class MissingNullableReturnTest { + public String get() { + return getInternal(true, null); + } + private String getInternal(boolean flag, @Nullable Integer i) { + return "hello"; + } + } + """) .doTest(); } @@ -1274,14 +1430,16 @@ public void negativeCases_lambda() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/MissingNullableReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import javax.annotation.Nullable;", - "import java.util.concurrent.Callable;", - "public class MissingNullableReturnTest {", - " public Callable get() {", - " return () -> { return null; };", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import javax.annotation.Nullable; + import java.util.concurrent.Callable; + public class MissingNullableReturnTest { + public Callable get() { + return () -> { return null; }; + } + } + """) .doTest(); } @@ -1290,13 +1448,15 @@ public void negativeCases_staticNonFinalField() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " static Object NULL = null;", - " Object get() {", - " return NULL;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + static Object NULL = null; + Object get() { + return NULL; + } + } + """) .doTest(); } @@ -1305,17 +1465,19 @@ public void negativeCases_polyNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import org.checkerframework.checker.nullness.qual.PolyNull;", - "public class LiteralNullReturnTest {", - " public @PolyNull String getMessage(@PolyNull String s) {", - " if (s == null) {", - " return null;", - " } else {", - " return \"negative\";", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import org.checkerframework.checker.nullness.qual.PolyNull; + public class LiteralNullReturnTest { + public @PolyNull String getMessage(@PolyNull String s) { + if (s == null) { + return null; + } else { + return "negative"; + } + } + } + """) .doTest(); } @@ -1324,13 +1486,15 @@ public void negativeCases_unreachableExit() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "class LiteralNullReturnTest {", - " public String getMessage() {", - " System.exit(1);", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + class LiteralNullReturnTest { + public String getMessage() { + System.exit(1); + return null; + } + } + """) .doTest(); } @@ -1339,14 +1503,16 @@ public void negativeCases_unreachableAssertFail() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import static org.junit.Assert.fail;", - "class LiteralNullReturnTest {", - " public String getMessage() {", - " fail();", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import static org.junit.Assert.fail; + class LiteralNullReturnTest { + public String getMessage() { + fail(); + return null; + } + } + """) .doTest(); } @@ -1355,14 +1521,16 @@ public void negativeCases_unreachableTestCaseFail() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import static junit.framework.TestCase.fail;", - "class LiteralNullReturnTest {", - " public String getMessage() {", - " fail();", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import static junit.framework.TestCase.fail; + class LiteralNullReturnTest { + public String getMessage() { + fail(); + return null; + } + } + """) .doTest(); } @@ -1371,20 +1539,24 @@ public void negativeCases_unreachableFailNonCanonicalImport() { createCompilationTestHelper() .addSourceLines( "com/foo/BarTestCase.java", - "package foo;", - "import junit.framework.TestCase;", - "class BarTestCase extends TestCase {", - "}") + """ + package foo; + import junit.framework.TestCase; + class BarTestCase extends TestCase { + } + """) .addSourceLines( "com/foo/OtherTestCase.java", - "package foo;", - "import static foo.BarTestCase.fail;", - "class OtherTestCase {", - " public String getMessage() {", - " fail();", - " return null;", - " }", - "}") + """ + package foo; + import static foo.BarTestCase.fail; + class OtherTestCase { + public String getMessage() { + fail(); + return null; + } + } + """) .doTest(); } @@ -1393,15 +1565,17 @@ public void negativeCases_unreachableThrowExceptionMethod() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import static org.junit.Assert.fail;", - "class LiteralNullReturnTest {", - " void throwRuntimeException() {}", - " public String getMessage() {", - " throwRuntimeException();", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import static org.junit.Assert.fail; + class LiteralNullReturnTest { + void throwRuntimeException() {} + public String getMessage() { + throwRuntimeException(); + return null; + } + } + """) .doTest(); } @@ -1410,14 +1584,16 @@ public void negativeCases_unreachableCheckFalse() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import static com.google.common.base.Preconditions.checkState;", - "class LiteralNullReturnTest {", - " public String getMessage() {", - " checkState(false);", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import static com.google.common.base.Preconditions.checkState; + class LiteralNullReturnTest { + public String getMessage() { + checkState(false); + return null; + } + } + """) .doTest(); } @@ -1426,14 +1602,16 @@ public void negativeCases_unreachableVerifyFalse() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import static com.google.common.base.Verify.verify;", - "class LiteralNullReturnTest {", - " public String getMessage() {", - " verify(false);", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import static com.google.common.base.Verify.verify; + class LiteralNullReturnTest { + public String getMessage() { + verify(false); + return null; + } + } + """) .doTest(); } @@ -1442,13 +1620,15 @@ public void negativeCases_staticFinalNonNullField() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " static final Object SOMETHING = 1;", - " Object get() {", - " return SOMETHING;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + static final Object SOMETHING = 1; + Object get() { + return SOMETHING; + } + } + """) .doTest(); } @@ -1457,12 +1637,14 @@ public void negativeCases_returnXIfXIsNotNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " return (o != null ? o : \"\");", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + return (o != null ? o : ""); + } + } + """) .doTest(); } @@ -1471,13 +1653,15 @@ public void negativeCases_returnXIfSameSymbolDifferentObjectIsNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object o;", - " Object foo(LiteralNullReturnTest other) {", - " return (o == null ? other.o : \"\");", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object o; + Object foo(LiteralNullReturnTest other) { + return (o == null ? other.o : ""); + } + } + """) .doTest(); } @@ -1486,12 +1670,14 @@ public void negativeCases_returnXUnlessXIsXNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " return (o == null ? \"\" : o);", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + return (o == null ? "" : o); + } + } + """) .doTest(); } @@ -1500,15 +1686,17 @@ public void negativeCases_returnXInsideIfNotNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " if (o != null) {", - " return o;", - " }", - " return \"\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + if (o != null) { + return o; + } + return ""; + } + } + """) .doTest(); } @@ -1517,16 +1705,18 @@ public void negativeCases_returnXInsideIfNullElse() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " if (o == null) {", - " return \"\";", - " } else {", - " return o;", - " }", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + if (o == null) { + return ""; + } else { + return o; + } + } + } + """) .doTest(); } @@ -1535,16 +1725,18 @@ public void negativeCases_returnXInsideIfNullButAfterOtherStatement() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object foo(Object o) {", - " if (o == null) {", - " o = \"\";", - " return o;", - " }", - " return \"\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object foo(Object o) { + if (o == null) { + o = ""; + return o; + } + return ""; + } + } + """) .doTest(); } @@ -1554,12 +1746,14 @@ public void negativeCases_onlyIfAlreadyInScopeAndItIsNot() { .setArgs("-XepOpt:Nullness:OnlyIfAnnotationAlreadyInScope=true") .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " String getMessage(boolean b) {", - " return b ? \"\" : null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + String getMessage(boolean b) { + return b ? "" : null; + } + } + """) .doTest(); } @@ -1568,13 +1762,15 @@ public void negativeCases_orElseNotNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import java.util.Optional;", - "class LiteralNullReturnTest {", - " public String getMessage(Optional m) {", - " return m.orElse(\"\");", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import java.util.Optional; + class LiteralNullReturnTest { + public String getMessage(Optional m) { + return m.orElse(""); + } + } + """) .doTest(); } @@ -1583,16 +1779,20 @@ public void negativeCases_doesNotImplementMap() { createCompilationTestHelper() .addSourceLines( "NotMap.java", - "interface NotMap {", - " String get(Object o);", - " V replace(K k, V v);", - "}") + """ + interface NotMap { + String get(Object o); + V replace(K k, V v); + } + """) .addSourceLines( "MyMap.java", - "interface MyMap extends NotMap {", - " @Override String get(Object o);", - " @Override Double replace(Integer k, Double v);", - "}") + """ + interface MyMap extends NotMap { + @Override String get(Object o); + @Override Double replace(Integer k, Double v); + } + """) .doTest(); } @@ -1601,14 +1801,16 @@ public void negativeCases_suppressionForReturnTreeBased() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "import java.util.Optional;", - "class LiteralNullReturnTest {", - " @SuppressWarnings(\"ReturnMissingNullable\")", - " public String getMessage(Optional m) {", - " return m.orElse(null);", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + import java.util.Optional; + class LiteralNullReturnTest { + @SuppressWarnings("ReturnMissingNullable") + public String getMessage(Optional m) { + return m.orElse(null); + } + } + """) .doTest(); } @@ -1616,17 +1818,21 @@ public void negativeCases_suppressionForReturnTreeBased() { public void negativeCases_suppressionForMethodTreeBased() { createCompilationTestHelper() .addSourceLines( - "NotMap.java", // - "interface NotMap {", - " Integer get(String o);", - "}") + "NotMap.java", + """ + interface NotMap { + Integer get(String o); + } + """) .addSourceLines( "MyMap.java", - "import java.util.Map;", - "interface MyMap extends Map, NotMap {", - " @SuppressWarnings(\"ReturnMissingNullable\")", - " @Override V get(Object o);", - "}") + """ + import java.util.Map; + interface MyMap extends Map, NotMap { + @SuppressWarnings("ReturnMissingNullable") + @Override V get(Object o); + } + """) .doTest(); } @@ -1634,17 +1840,21 @@ public void negativeCases_suppressionForMethodTreeBased() { public void negativeCases_suppressionAboveMethodLevel() { createCompilationTestHelper() .addSourceLines( - "NotMap.java", // - "interface NotMap {", - " Integer get(String o);", - "}") + "NotMap.java", + """ + interface NotMap { + Integer get(String o); + } + """) .addSourceLines( "MyMap.java", - "import java.util.Map;", - "@SuppressWarnings(\"ReturnMissingNullable\")", - "interface MyMap extends Map, NotMap {", - " @Override V get(Object o);", - "}") + """ + import java.util.Map; + @SuppressWarnings("ReturnMissingNullable") + interface MyMap extends Map, NotMap { + @Override V get(Object o); + } + """) .doTest(); } @@ -1653,10 +1863,12 @@ public void negativeCases_implementsMapButRunningInConservativeMode() { createCompilationTestHelper() .addSourceLines( "MyMap.java", - "import java.util.Map;", - "interface MyMap extends Map {", - " @Override V get(Object o);", - "}") + """ + import java.util.Map; + interface MyMap extends Map { + @Override V get(Object o); + } + """) .doTest(); } @@ -1665,16 +1877,18 @@ public void returnSameSymbolDifferentObjectInsideIfNull() { createCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "abstract class LiteralNullReturnTest {", - " Object o;", - " Object foo(LiteralNullReturnTest other) {", - " if (o == null) {", - " return other.o;", - " }", - " return \"\";", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + abstract class LiteralNullReturnTest { + Object o; + Object foo(LiteralNullReturnTest other) { + if (o == null) { + return other.o; + } + return ""; + } + } + """) .doTest(); } @@ -1683,18 +1897,22 @@ public void suggestNonJsr305Nullable() { createRefactoringTestHelper() .addInputLines( "in/Test.java", - "class T {", - " @Nullable private final Object obj1 = null;", - " private final Object method(boolean b) { return b ? null : 0; }", - " @interface Nullable {}", - "}") + """ + class T { + @Nullable private final Object obj1 = null; + private final Object method(boolean b) { return b ? null : 0; } + @interface Nullable {} + } + """) .addOutputLines( "out/Test.java", - "class T {", - " @Nullable private final Object obj1 = null;", - " @Nullable private final Object method(boolean b) { return b ? null : 0; }", - " @interface Nullable {}", - "}") + """ + class T { + @Nullable private final Object obj1 = null; + @Nullable private final Object method(boolean b) { return b ? null : 0; } + @interface Nullable {} + } + """) .doTest(); } @@ -1703,17 +1921,20 @@ public void nonAnnotationNullable() { createRefactoringTestHelper() .addInputLines( "in/Test.java", - "class T {", - " private final Object method(boolean b) { return b ? null : 0; }", - " class Nullable {}", - "}") + """ + class T { + private final Object method(boolean b) { return b ? null : 0; } + class Nullable {} + } + """) .addOutputLines( "out/Test.java", - "class T {", - " @org.jspecify.annotations.Nullable private final Object method(boolean b) { return b" - + " ? null : 0; }", - " class Nullable {}", - "}") + """ +class T { + @org.jspecify.annotations.Nullable private final Object method(boolean b) { return b ? null : 0; } + class Nullable {} +} +""") .doTest(); } @@ -1722,27 +1943,31 @@ public void multipleNullReturns() { createRefactoringTestHelper() .addInputLines( "in/Test.java", - "class T {", - " private final Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + class T { + private final Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .addOutputLines( "out/Test.java", - "import org.jspecify.annotations.Nullable;", - "class T {", - " private final @Nullable Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.jspecify.annotations.Nullable; + class T { + private final @Nullable Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .doTest(); } @@ -1751,28 +1976,32 @@ public void memberSelectReturnType() { createRefactoringTestHelper() .addInputLines( "in/Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "class T {", - " java.lang.Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + class T { + java.lang.Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .addOutputLines( "out/Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "class T {", - " java.lang.@Nullable Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + class T { + java.lang.@Nullable Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .doTest(); } @@ -1781,28 +2010,32 @@ public void annotationInsertedAfterModifiers() { createRefactoringTestHelper() .addInputLines( "in/Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "class T {", - " final Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + class T { + final Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .addOutputLines( "out/Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "class T {", - " final @Nullable Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + class T { + final @Nullable Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .doTest(TEXT_MATCH); } @@ -1811,28 +2044,32 @@ public void parameterizedMemberSelectReturnType() { createRefactoringTestHelper() .addInputLines( "in/Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "class T {", - " java.util.List method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + class T { + java.util.List method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .addOutputLines( "out/Test.java", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "class T {", - " java.util.@Nullable List method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.checkerframework.checker.nullness.qual.Nullable; + class T { + java.util.@Nullable List method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .doTest(); } @@ -1841,30 +2078,34 @@ public void annotatedMemberSelectReturnType() { createRefactoringTestHelper() .addInputLines( "in/Test.java", - "import org.checkerframework.checker.initialization.qual.UnderInitialization;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "class T {", - " java.lang.@UnderInitialization Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.checkerframework.checker.initialization.qual.UnderInitialization; + import org.checkerframework.checker.nullness.qual.Nullable; + class T { + java.lang.@UnderInitialization Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .addOutputLines( "out/Test.java", - "import org.checkerframework.checker.initialization.qual.UnderInitialization;", - "import org.checkerframework.checker.nullness.qual.Nullable;", - "class T {", - " java.lang.@Nullable @UnderInitialization Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import org.checkerframework.checker.initialization.qual.UnderInitialization; + import org.checkerframework.checker.nullness.qual.Nullable; + class T { + java.lang.@Nullable @UnderInitialization Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .doTest(); } @@ -1874,27 +2115,31 @@ public void annotationNotNamedNullable() { .setArgs("-XepOpt:Nullness:DefaultNullnessAnnotation=javax.annotation.CheckForNull") .addInputLines( "in/Test.java", - "class T {", - " Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + class T { + Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .addOutputLines( "out/Test.java", - "import javax.annotation.CheckForNull;", - "class T {", - " @CheckForNull Object method(boolean b) {", - " if (b) {", - " return null;", - " } else {", - " return null;", - " }", - " }", - "}") + """ + import javax.annotation.CheckForNull; + class T { + @CheckForNull Object method(boolean b) { + if (b) { + return null; + } else { + return null; + } + } + } + """) .doTest(); } @@ -1903,13 +2148,15 @@ public void aggressive_onlyStatementIsNullReturn() { createAggressiveCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public String getMessage() {", - " // BUG: Diagnostic contains: @Nullable", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public String getMessage() { + // BUG: Diagnostic contains: @Nullable + return null; + } + } + """) .doTest(); } @@ -1918,13 +2165,15 @@ public void aggressive_typeVariableUsage() { createAggressiveCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " public T getMessage(boolean b, T t) {", - " // BUG: Diagnostic contains: @Nullable", - " return b ? null : t;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + public T getMessage(boolean b, T t) { + // BUG: Diagnostic contains: @Nullable + return b ? null : t; + } + } + """) .doTest(); } @@ -1933,16 +2182,18 @@ public void aggressive_voidTypedMethod() { createAggressiveCompilationTestHelper() .addSourceLines( "com/google/errorprone/bugpatterns/nullness/VoidTypeTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class VoidTypeTest {", - " public Void run(int iterations) {", - " // BUG: Diagnostic contains: @Nullable", - " if (iterations <= 0) { return null; }", - " run(iterations - 1);", - " // BUG: Diagnostic contains: @Nullable", - " return null;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class VoidTypeTest { + public Void run(int iterations) { + // BUG: Diagnostic contains: @Nullable + if (iterations <= 0) { return null; } + run(iterations - 1); + // BUG: Diagnostic contains: @Nullable + return null; + } + } + """) .doTest(); } @@ -1952,38 +2203,42 @@ public void negativeCases_doesNotRemoveNecessarySuppressWarnings() { .setArgs("-XepOpt:Nullness:RemoveSuppressWarnings=true") .addInputLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " @SuppressWarnings(\"nullness:argument\")", - " public String getMessage(boolean b) {", - " if (b) {", - " doSomethingElse(null);", - " return \"negative\";", - " } else {", - " return \"negative\";", - " }", - " }", - " public void doSomethingElse(Object c) {", - " return;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + @SuppressWarnings("nullness:argument") + public String getMessage(boolean b) { + if (b) { + doSomethingElse(null); + return "negative"; + } else { + return "negative"; + } + } + public void doSomethingElse(Object c) { + return; + } + } + """) .addOutputLines( "com/google/errorprone/bugpatterns/nullness/LiteralNullReturnTest.java", - "package com.google.errorprone.bugpatterns.nullness;", - "public class LiteralNullReturnTest {", - " @SuppressWarnings(\"nullness:argument\")", - " public String getMessage(boolean b) {", - " if (b) {", - " doSomethingElse(null);", - " return \"negative\";", - " } else {", - " return \"negative\";", - " }", - " }", - " public void doSomethingElse(Object c) {", - " return;", - " }", - "}") + """ + package com.google.errorprone.bugpatterns.nullness; + public class LiteralNullReturnTest { + @SuppressWarnings("nullness:argument") + public String getMessage(boolean b) { + if (b) { + doSomethingElse(null); + return "negative"; + } else { + return "negative"; + } + } + public void doSomethingElse(Object c) { + return; + } + } + """) .doTest(TEXT_MATCH); } @@ -1991,21 +2246,25 @@ public void negativeCases_doesNotRemoveNecessarySuppressWarnings() { public void aggressive_implementsMap() { createAggressiveCompilationTestHelper() .addSourceLines( - "NotMap.java", // - "interface NotMap {", - " Integer get(String o);", - "}") + "NotMap.java", + """ + interface NotMap { + Integer get(String o); + } + """) .addSourceLines( "MyMap.java", - "import java.util.Map;", - "interface MyMap extends Map, NotMap {", - " // BUG: Diagnostic contains: @Nullable", - " @Override V get(Object o);", - " // BUG: Diagnostic contains: @Nullable", - " @Override V replace(K k, V v);", - " @Override boolean replace(K k, V expect, V update);", - " @Override Integer get(String o);", - "}") + """ + import java.util.Map; + interface MyMap extends Map, NotMap { + // BUG: Diagnostic contains: @Nullable + @Override V get(Object o); + // BUG: Diagnostic contains: @Nullable + @Override V replace(K k, V v); + @Override boolean replace(K k, V expect, V update); + @Override Integer get(String o); + } + """) .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/UnsafeWildcardTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/UnsafeWildcardTest.java index 8c24d0437d5..a7867903389 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/UnsafeWildcardTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/UnsafeWildcardTest.java @@ -38,50 +38,52 @@ public void positiveExpressions() { compilationHelper .addSourceLines( "Test.java", - "import java.util.List;", - "class Test {", - " static class WithBound {}", - " public WithBound basic() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return null;", - " }", - " public WithBound inParens() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return (null);", - " }", - " public WithBound cast() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return (WithBound) null;", - " }", - " public WithBound inTernary(boolean x, WithBound dflt) {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return x ? null : dflt;", - " }", - " public WithBound allNullTernary(boolean x) {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return x ? null : null;", - " }", - " public WithBound parensInTernary(boolean x) {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return x ? (null) : null;", - " }", - " public WithBound parensAroundTernary(boolean x) {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return (x ? null : null);", - " }", - " public List> nestedWildcard() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return null;", - " }", - " public List> extendsWildcard() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return null;", - " }", - " public List> superWildcard() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return null;", - " }", - "}") + """ + import java.util.List; + class Test { + static class WithBound {} + public WithBound basic() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return null; + } + public WithBound inParens() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return (null); + } + public WithBound cast() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return (WithBound) null; + } + public WithBound inTernary(boolean x, WithBound dflt) { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return x ? null : dflt; + } + public WithBound allNullTernary(boolean x) { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return x ? null : null; + } + public WithBound parensInTernary(boolean x) { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return x ? (null) : null; + } + public WithBound parensAroundTernary(boolean x) { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return (x ? null : null); + } + public List> nestedWildcard() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return null; + } + public List> extendsWildcard() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return null; + } + public List> superWildcard() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return null; + } + } + """) .doTest(); } @@ -90,36 +92,38 @@ public void negativeReturns() { compilationHelper .addSourceLines( "Test.java", - "import java.util.List;", - "class Test {", - " public String basic() {", - " return null;", - " }", - " public String inParens() {", - " return (null);", - " }", - " public String inTernary(boolean x) {", - " return x ? null : \"foo\";", - " }", - " public String allNullTernary(boolean x) {", - " return x ? null : null;", - " }", - " public String parensInTernary(boolean x) {", - " return x ? (null) : \"foo\";", - " }", - " public String parensAroundTernary(boolean x) {", - " return (x ? null : \"foo\");", - " }", - " public List typearg() {", - " return null;", - " }", - " public List extendsWildcard() {", - " return null;", - " }", - " public List superWildcardNoImplicitBound() {", - " return null;", - " }", - "}") + """ + import java.util.List; + class Test { + public String basic() { + return null; + } + public String inParens() { + return (null); + } + public String inTernary(boolean x) { + return x ? null : "foo"; + } + public String allNullTernary(boolean x) { + return x ? null : null; + } + public String parensInTernary(boolean x) { + return x ? (null) : "foo"; + } + public String parensAroundTernary(boolean x) { + return (x ? null : "foo"); + } + public List typearg() { + return null; + } + public List extendsWildcard() { + return null; + } + public List superWildcardNoImplicitBound() { + return null; + } + } + """) .doTest(); } @@ -128,22 +132,24 @@ public void negativeLambdas() { compilationHelper .addSourceLines( "Test.java", - "import java.util.List;", - "import java.util.function.Function;", - "class Test {", - " public Function basic() {", - " return x -> null;", - " }", - " public Function inParens() {", - " return x -> (null);", - " }", - " public Function inTernary() {", - " return x -> x ? null : \"foo\";", - " }", - " public Function returnInLambda() {", - " return x -> { return null; };", - " }", - "}") + """ + import java.util.List; + import java.util.function.Function; + class Test { + public Function basic() { + return x -> null; + } + public Function inParens() { + return x -> (null); + } + public Function inTernary() { + return x -> x ? null : "foo"; + } + public Function returnInLambda() { + return x -> { return null; }; + } + } + """) .doTest(); } @@ -152,29 +158,31 @@ public void lambdasWithTypeParameters() { compilationHelper .addSourceLines( "Test.java", - "import java.util.List;", - "import java.util.function.Function;", - "class Test {", - " class WithBound {}", - " public Function> contra() {", - " return s -> null;", - " }", - " public Function> implicitOk() {", - " return i -> null;", - " }", - " public Function> implicitPositive() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return u -> null;", - " }", - " public Function> returnInLambda() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return u -> { return null; };", - " }", - " public Function> nestedWildcard() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return null;", - " }", - "}") + """ + import java.util.List; + import java.util.function.Function; + class Test { + class WithBound {} + public Function> contra() { + return s -> null; + } + public Function> implicitOk() { + return i -> null; + } + public Function> implicitPositive() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return u -> null; + } + public Function> returnInLambda() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return u -> { return null; }; + } + public Function> nestedWildcard() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return null; + } + } + """) .doTest(); } @@ -183,28 +191,30 @@ public void typeParameters() { compilationHelper .addSourceLines( "Test.java", - "import java.util.List;", - "class Test {", - " static class WithBound {}", - " class WildcardBound> {", - " T bad() {", - " // We allow this and instead check instantiations below", - " return null;", - " }", - " }", - " WildcardBound> diamond() {", - " // BUG: Diagnostic contains: Unsafe wildcard type argument", - " return new WildcardBound<>();", - " }", - " WildcardBound> create() {", - " // BUG: Diagnostic contains: Unsafe wildcard type argument", - " return new WildcardBound>();", - " }", - " WildcardBound> none() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return null;", - " }", - "}") + """ + import java.util.List; + class Test { + static class WithBound {} + class WildcardBound> { + T bad() { + // We allow this and instead check instantiations below + return null; + } + } + WildcardBound> diamond() { + // BUG: Diagnostic contains: Unsafe wildcard type argument + return new WildcardBound<>(); + } + WildcardBound> create() { + // BUG: Diagnostic contains: Unsafe wildcard type argument + return new WildcardBound>(); + } + WildcardBound> none() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return null; + } + } + """) .doTest(); } @@ -213,47 +223,49 @@ public void variables() { compilationHelper .addSourceLines( "Test.java", - "import java.util.List;", - "class Test {", - " class WithBound {}", - " private String s;", - " private List xs = null;", - " private List ys;", - " private WithBound zs = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " private WithBound initialized = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " private final WithBound initializedFinal = null;", - " // BUG: Diagnostic contains: Uninitialized field with unsafe wildcard", - " private WithBound uninitialized;", - " private final WithBound uninitializedFinal;", - " Test() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " uninitializedFinal = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " uninitialized = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " initialized = null;", - " }", - " public void foo() {", - " List covariant = null;", - " List contravariant = null;", - " WithBound inBounds = null;", - " WithBound uninitializedLocal;", - " final WithBound uninitializedFinalLocal;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " WithBound implicitBounds = null;", - " covariant = null;", - " contravariant = null;", - " inBounds = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " uninitializedLocal = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " uninitializedFinalLocal = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " implicitBounds = null;", - " }", - "}") + """ + import java.util.List; + class Test { + class WithBound {} + private String s; + private List xs = null; + private List ys; + private WithBound zs = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + private WithBound initialized = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + private final WithBound initializedFinal = null; + // BUG: Diagnostic contains: Uninitialized field with unsafe wildcard + private WithBound uninitialized; + private final WithBound uninitializedFinal; + Test() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + uninitializedFinal = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + uninitialized = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + initialized = null; + } + public void foo() { + List covariant = null; + List contravariant = null; + WithBound inBounds = null; + WithBound uninitializedLocal; + final WithBound uninitializedFinalLocal; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + WithBound implicitBounds = null; + covariant = null; + contravariant = null; + inBounds = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + uninitializedLocal = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + uninitializedFinalLocal = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + implicitBounds = null; + } + } + """) .doTest(); } @@ -308,41 +320,43 @@ public void constructors() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " class WithBound {}", - " public Test() { this(null, null); }", - " public Test(WithBound implicit) {}", - " public Test(WithBound xs, WithBound contra) {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " this(null);", - " }", - " class Sub extends Test {", - " Sub(WithBound implicit) {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " super(null);", - " }", - " }", - " static Test newClass() {", - " new Test(null, null);", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " new Test(null);", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " return new Test<>(null);", - " }", - " static Test anonymous() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " new Test(null) {};", - " return null;", - " }", - " void inner() {", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " new Sub(null);", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " new Sub(null) {};", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " this.new Sub(null) {};", - " }", - "}") + """ + class Test { + class WithBound {} + public Test() { this(null, null); } + public Test(WithBound implicit) {} + public Test(WithBound xs, WithBound contra) { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + this(null); + } + class Sub extends Test { + Sub(WithBound implicit) { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + super(null); + } + } + static Test newClass() { + new Test(null, null); + // BUG: Diagnostic contains: Cast to wildcard type unsafe + new Test(null); + // BUG: Diagnostic contains: Cast to wildcard type unsafe + return new Test<>(null); + } + static Test anonymous() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + new Test(null) {}; + return null; + } + void inner() { + // BUG: Diagnostic contains: Cast to wildcard type unsafe + new Sub(null); + // BUG: Diagnostic contains: Cast to wildcard type unsafe + new Sub(null) {}; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + this.new Sub(null) {}; + } + } + """) .doTest(); } @@ -351,20 +365,22 @@ public void supertypes_problematicWildcards_flagged() { compilationHelper .addSourceLines( "Test.java", - "import java.io.Serializable;", - "import java.util.AbstractList;", - "import java.util.List;", - "class Test {", - " class WithBound {}", - " // BUG: Diagnostic contains: Unsafe wildcard type", - " abstract class BadList extends AbstractList> {}", - " abstract class BadListImpl implements Serializable,", - " // BUG: Diagnostic contains: Unsafe wildcard type", - " List> {}", - " interface BadListItf extends Serializable,", - " // BUG: Diagnostic contains: Unsafe wildcard type", - " List> {}", - "}") + """ + import java.io.Serializable; + import java.util.AbstractList; + import java.util.List; + class Test { + class WithBound {} + // BUG: Diagnostic contains: Unsafe wildcard type + abstract class BadList extends AbstractList> {} + abstract class BadListImpl implements Serializable, + // BUG: Diagnostic contains: Unsafe wildcard type + List> {} + interface BadListItf extends Serializable, + // BUG: Diagnostic contains: Unsafe wildcard type + List> {} + } + """) .doTest(); } @@ -428,25 +444,27 @@ public void genericArrays_isCompilerError() { compilationHelper .addSourceLines( "Test.java", - "class Test {", - " class WithBound {}", - " // BUG: Diagnostic matches: X", - " WithBound[] simpleInitializer = { null };", - " // BUG: Diagnostic matches: X", - " WithBound[][] nestedInitializer = { { null }, { null } };", - " // BUG: Diagnostic matches: X", - " WithBound[][] emptyInitializer = {};", - " void newArrays() {", - " // BUG: Diagnostic matches: X", - " Object[] a1 = new WithBound[] {};", - " // BUG: Diagnostic matches: X", - " Object[] a2 = new WithBound[0];", - " // BUG: Diagnostic matches: X", - " Object[] a3 = new WithBound[][] {};", - " // BUG: Diagnostic matches: X", - " Object[] a4 = new WithBound[0][];", - " }", - "}") + """ + class Test { + class WithBound {} + // BUG: Diagnostic matches: X + WithBound[] simpleInitializer = { null }; + // BUG: Diagnostic matches: X + WithBound[][] nestedInitializer = { { null }, { null } }; + // BUG: Diagnostic matches: X + WithBound[][] emptyInitializer = {}; + void newArrays() { + // BUG: Diagnostic matches: X + Object[] a1 = new WithBound[] {}; + // BUG: Diagnostic matches: X + Object[] a2 = new WithBound[0]; + // BUG: Diagnostic matches: X + Object[] a3 = new WithBound[][] {}; + // BUG: Diagnostic matches: X + Object[] a4 = new WithBound[0][]; + } + } + """) .expectResult(Result.ERROR) .matchAllDiagnostics() .expectErrorMessage("X", msg -> msg.contains("generic array creation")) @@ -484,15 +502,17 @@ public void boundedTypeVar_validLowerBound_isIgnored() { compilationHelper .addSourceLines( "MyIterable.java", - "import java.util.List;", - "interface MyIterable> {", - " static class Test> implements MyIterable {", - " MyIterable parent;", - " public Test() {", - " this.parent = null;", - " }", - " }", - "}") + """ + import java.util.List; + interface MyIterable> { + static class Test> implements MyIterable { + MyIterable parent; + public Test() { + this.parent = null; + } + } + } + """) .doTest(); } @@ -501,16 +521,18 @@ public void boundedTypeVar_questionableLowerBound_isCompilerError() { compilationHelper .addSourceLines( "MyIterable.java", - "import java.util.List;", - "interface MyIterable> {", - " // BUG: Diagnostic matches: X", - " static class Test> implements MyIterable {", - " MyIterable parent;", - " public Test() {", - " this.parent = null;", - " }", - " }", - "}") + """ + import java.util.List; + interface MyIterable> { + // BUG: Diagnostic matches: X + static class Test> implements MyIterable { + MyIterable parent; + public Test() { + this.parent = null; + } + } + } + """) .expectResult(Result.ERROR) .matchAllDiagnostics() .expectErrorMessage( @@ -529,17 +551,19 @@ public void fBoundedImplicitUpperBound_validLowerBound_isIgnored() { compilationHelper .addSourceLines( "FBounded.java", - "abstract class FBounded> {", - " public static final class Coll extends FBounded> {}", - " public interface Listener> {}", - " public static void shouldWork() {", - " Listener> validListener = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " Listener invalidListener = null;", - " // BUG: Diagnostic contains: Cast to wildcard type unsafe", - " Iterable> invalidListeners = java.util.List.of(null, null);", - " }", - "}") + """ + abstract class FBounded> { + public static final class Coll extends FBounded> {} + public interface Listener> {} + public static void shouldWork() { + Listener> validListener = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + Listener invalidListener = null; + // BUG: Diagnostic contains: Cast to wildcard type unsafe + Iterable> invalidListeners = java.util.List.of(null, null); + } + } + """) .doTest(); } @@ -548,14 +572,16 @@ public void fBoundedImplicitUpperBound_invalidLowerBound_isCompilerError() { compilationHelper .addSourceLines( "FBounded.java", - "abstract class FBounded> {", - " public static final class Coll extends FBounded> {}", - " public interface Listener> {}", - " public static void shouldWork() {", - " // BUG: Diagnostic matches: X", - " Listener listener = null;", - " }", - "}") + """ + abstract class FBounded> { + public static final class Coll extends FBounded> {} + public interface Listener> {} + public static void shouldWork() { + // BUG: Diagnostic matches: X + Listener listener = null; + } + } + """) .expectResult(Result.ERROR) .matchAllDiagnostics() .expectErrorMessage( diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/GuardedByCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/GuardedByCheckerTest.java index e402075294f..378be9bef51 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/GuardedByCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/GuardedByCheckerTest.java @@ -33,30 +33,32 @@ public void locked() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " final Lock lock = null;", - " @GuardedBy(\"lock\")", - " int x;", - " void m() {", - " lock.lock();", - " // BUG: Diagnostic contains:", - " // access should be guarded by 'this.lock'", - " x++;", - " try {", - " x++;", - " } catch (Exception e) {", - " x--;", - " } finally {", - " lock.unlock();", - " }", - " // BUG: Diagnostic contains:", - " // access should be guarded by 'this.lock'", - " x++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.locks.Lock; + class Test { + final Lock lock = null; + @GuardedBy("lock") + int x; + void m() { + lock.lock(); + // BUG: Diagnostic contains: + // access should be guarded by 'this.lock' + x++; + try { + x++; + } catch (Exception e) { + x--; + } finally { + lock.unlock(); + } + // BUG: Diagnostic contains: + // access should be guarded by 'this.lock' + x++; + } + } + """) .doTest(); } @@ -66,16 +68,18 @@ public void staticLocked() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " @GuardedBy(\"Test.class\")", - " static int x;", - " static synchronized void m() {", - " x++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.locks.Lock; + class Test { + @GuardedBy("Test.class") + static int x; + static synchronized void m() { + x++; + } + } + """) .doTest(); } @@ -84,28 +88,30 @@ public void monitor() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import com.google.common.util.concurrent.Monitor;", - "class Test {", - " final Monitor monitor = null;", - " @GuardedBy(\"monitor\")", - " int x;", - " void m() {", - " monitor.enter();", - " // BUG: Diagnostic contains:", - " // access should be guarded by 'this.monitor'", - " x++;", - " try {", - " x++;", - " } finally {", - " monitor.leave();", - " }", - " // BUG: Diagnostic contains:", - " // access should be guarded by 'this.monitor'", - " x++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import com.google.common.util.concurrent.Monitor; + class Test { + final Monitor monitor = null; + @GuardedBy("monitor") + int x; + void m() { + monitor.enter(); + // BUG: Diagnostic contains: + // access should be guarded by 'this.monitor' + x++; + try { + x++; + } finally { + monitor.leave(); + } + // BUG: Diagnostic contains: + // access should be guarded by 'this.monitor' + x++; + } + } + """) .doTest(); } @@ -114,25 +120,27 @@ public void wrongLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " final Lock lock1 = null;", - " final Lock lock2 = null;", - " @GuardedBy(\"lock1\")", - " int x;", - " void m() {", - " lock2.lock();", - " try {", - " // BUG: Diagnostic contains:", - " // access should be guarded by 'this.lock1'", - " x++;", - " } finally {", - " lock2.unlock();", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.locks.Lock; + class Test { + final Lock lock1 = null; + final Lock lock2 = null; + @GuardedBy("lock1") + int x; + void m() { + lock2.lock(); + try { + // BUG: Diagnostic contains: + // access should be guarded by 'this.lock1' + x++; + } finally { + lock2.unlock(); + } + } + } + """) .doTest(); } @@ -141,18 +149,20 @@ public void guardedStaticFieldAccess_1() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " public static final Object lock = new Object();", - " @GuardedBy(\"lock\")", - " public static int x;", - " void m() {", - " synchronized (Test.lock) {", - " Test.x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + public static final Object lock = new Object(); + @GuardedBy("lock") + public static int x; + void m() { + synchronized (Test.lock) { + Test.x++; + } + } + } + """) .doTest(); } @@ -161,18 +171,20 @@ public void guardedStaticFieldAccess_2() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " public static final Object lock = new Object();", - " @GuardedBy(\"lock\")", - " public static int x;", - " void m() {", - " synchronized (lock) {", - " Test.x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + public static final Object lock = new Object(); + @GuardedBy("lock") + public static int x; + void m() { + synchronized (lock) { + Test.x++; + } + } + } + """) .doTest(); } @@ -181,18 +193,20 @@ public void guardedStaticFieldAccess_3() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " public static final Object lock = new Object();", - " @GuardedBy(\"lock\")", - " public static int x;", - " void m() {", - " synchronized (Test.lock) {", - " x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + public static final Object lock = new Object(); + @GuardedBy("lock") + public static int x; + void m() { + synchronized (Test.lock) { + x++; + } + } + } + """) .doTest(); } @@ -201,15 +215,17 @@ public void guardedStaticFieldAccess_enclosingClass() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"Test.class\")", - " public static int x;", - " synchronized static void n() {", - " Test.x++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("Test.class") + public static int x; + synchronized static void n() { + Test.x++; + } + } + """) .doTest(); } @@ -218,18 +234,20 @@ public void badStaticFieldAccess() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " public static final Object lock = new Object();", - " @GuardedBy(\"lock\")", - " public static int x;", - " void m() {", - " // BUG: Diagnostic contains:", - " // access should be guarded by 'Test.lock'", - " Test.x++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + public static final Object lock = new Object(); + @GuardedBy("lock") + public static int x; + void m() { + // BUG: Diagnostic contains: + // access should be guarded by 'Test.lock' + Test.x++; + } + } + """) .doTest(); } @@ -238,12 +256,14 @@ public void badGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " // BUG: Diagnostic contains: Invalid @GuardedBy expression", - " @GuardedBy(\"foo\") int y;", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + // BUG: Diagnostic contains: Invalid @GuardedBy expression + @GuardedBy("foo") int y; + } + """) .doTest(); } @@ -252,12 +272,14 @@ public void errorProneAnnotation() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.GuardedBy;", - "class Test {", - " // BUG: Diagnostic contains: Invalid @GuardedBy expression", - " @GuardedBy(\"foo\") int y;", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.concurrent.GuardedBy; + class Test { + // BUG: Diagnostic contains: Invalid @GuardedBy expression + @GuardedBy("foo") int y; + } + """) .doTest(); } @@ -266,19 +288,21 @@ public void unheldInstanceGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " final Object mu = new Object();", - " @GuardedBy(\"mu\") int y;", - "}", - "class Main {", - " void m(Test t) {", - " // BUG: Diagnostic contains:", - " // should be guarded by 't.mu'", - " t.y++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + final Object mu = new Object(); + @GuardedBy("mu") int y; + } + class Main { + void m(Test t) { + // BUG: Diagnostic contains: + // should be guarded by 't.mu' + t.y++; + } + } + """) .doTest(); } @@ -287,17 +311,19 @@ public void unheldItselfGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Itself {", - " @GuardedBy(\"itself\")", - " int x;", - " void incrementX() {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'this.x'", - " x++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Itself { + @GuardedBy("itself") + int x; + void incrementX() { + // BUG: Diagnostic contains: + // should be guarded by 'this.x' + x++; + } + } + """) .doTest(); } @@ -306,22 +332,24 @@ public void i541() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import java.util.List;", - "import javax.annotation.concurrent.GuardedBy;", - "class Itself {", - " @GuardedBy(\"itself\")", - " List xs;", - " void f() {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'this.xs'", - " this.xs.add(\"\");", - " synchronized (this.xs) { this.xs.add(\"\"); }", - " synchronized (this.xs) { xs.add(\"\"); }", - " synchronized (xs) { this.xs.add(\"\"); }", - " synchronized (xs) { xs.add(\"\"); }", - " }", - "}") + """ + package threadsafety; + import java.util.List; + import javax.annotation.concurrent.GuardedBy; + class Itself { + @GuardedBy("itself") + List xs; + void f() { + // BUG: Diagnostic contains: + // should be guarded by 'this.xs' + this.xs.add(""); + synchronized (this.xs) { this.xs.add(""); } + synchronized (this.xs) { xs.add(""); } + synchronized (xs) { this.xs.add(""); } + synchronized (xs) { xs.add(""); } + } + } + """) .doTest(); } @@ -330,20 +358,22 @@ public void methodQualifiedWithThis() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import java.util.List;", - "import javax.annotation.concurrent.GuardedBy;", - "class Itself {", - " @GuardedBy(\"this\")", - " void f() {};", - " void g() {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'this'", - " this.f();", - " synchronized (this) { f(); }", - " synchronized (this) { this.f(); }", - " }", - "}") + """ + package threadsafety; + import java.util.List; + import javax.annotation.concurrent.GuardedBy; + class Itself { + @GuardedBy("this") + void f() {}; + void g() { + // BUG: Diagnostic contains: + // should be guarded by 'this' + this.f(); + synchronized (this) { f(); } + synchronized (this) { this.f(); } + } + } + """) .doTest(); } @@ -352,14 +382,16 @@ public void ctor() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"this\") int x;", - " public Test() {", - " this.x = 42;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("this") int x; + public Test() { + this.x = 42; + } + } + """) .doTest(); } @@ -368,15 +400,17 @@ public void badGuardMethodAccess() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"this\") void x() {}", - " void m() {", - " // BUG: Diagnostic contains: this", - " x();", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("this") void x() {} + void m() { + // BUG: Diagnostic contains: this + x(); + } + } + """) .doTest(); } @@ -385,14 +419,16 @@ public void transitiveGuardMethodAccess() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"this\") void x() {}", - " @GuardedBy(\"this\") void m() {", - " x();", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("this") void x() {} + @GuardedBy("this") void m() { + x(); + } + } + """) .doTest(); } @@ -436,29 +472,31 @@ public void readWriteLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.locks.ReentrantReadWriteLock;", - "class Test {", - " final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();", - " @GuardedBy(\"lock\") boolean b = false;", - " void m() {", - " lock.readLock().lock();", - " try {", - " b = true;", - " } finally {", - " lock.readLock().unlock();", - " }", - " }", - " void n() {", - " lock.writeLock().lock();", - " try {", - " b = true;", - " } finally {", - " lock.writeLock().unlock();", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.locks.ReentrantReadWriteLock; + class Test { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + @GuardedBy("lock") boolean b = false; + void m() { + lock.readLock().lock(); + try { + b = true; + } finally { + lock.readLock().unlock(); + } + } + void n() { + lock.writeLock().lock(); + try { + b = true; + } finally { + lock.writeLock().unlock(); + } + } + } + """) .doTest(); } @@ -468,19 +506,21 @@ public void readWriteLockIsIgnored() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.locks.ReentrantReadWriteLock;", - "class Test {", - " final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();", - " @GuardedBy(\"lock\") boolean b = false;", - " void m() {", - " try {", - " b = true;", - " } finally {", - " }", - " }", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.locks.ReentrantReadWriteLock; + class Test { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + @GuardedBy("lock") boolean b = false; + void m() { + try { + b = true; + } finally { + } + } + } + """) .doTest(); } @@ -489,23 +529,25 @@ public void innerClass_enclosingClassLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " final Object mu = new Object();", - " @GuardedBy(\"mu\") boolean b = false;", - " private final class Baz {", - " public void m() {", - " synchronized (mu) {", - " n();", - " }", - " }", - " @GuardedBy(\"Test.this.mu\")", - " private void n() {", - " b = true;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + final Object mu = new Object(); + @GuardedBy("mu") boolean b = false; + private final class Baz { + public void m() { + synchronized (mu) { + n(); + } + } + @GuardedBy("Test.this.mu") + private void n() { + b = true; + } + } + } + """) .doTest(); } @@ -515,18 +557,20 @@ public void innerClass_thisLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " @GuardedBy(\"this\") boolean b = false;", - " private final class Baz {", - " private synchronized void n() {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Test.this'", - " b = true;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + @GuardedBy("this") boolean b = false; + private final class Baz { + private synchronized void n() { + // BUG: Diagnostic contains: + // should be guarded by 'Test.this' + b = true; + } + } + } + """) .doTest(); } @@ -535,21 +579,23 @@ public void anonymousClass() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " @GuardedBy(\"this\") boolean b = false;", - " private synchronized void n() {", - " b = true;", - " new Object() {", - " void m() {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Test.this'", - " b = true;", - " }", - " };", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + @GuardedBy("this") boolean b = false; + private synchronized void n() { + b = true; + new Object() { + void m() { + // BUG: Diagnostic contains: + // should be guarded by 'Test.this' + b = true; + } + }; + } + } + """) .doTest(); } @@ -558,19 +604,21 @@ public void inheritedLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class A {", - " final Object lock = new Object();", - "}", - "class B extends A {", - " @GuardedBy(\"lock\") boolean b = false;", - " void m() {", - " synchronized (lock) {", - " b = true;", - " };", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class A { + final Object lock = new Object(); + } + class B extends A { + @GuardedBy("lock") boolean b = false; + void m() { + synchronized (lock) { + b = true; + }; + } + } + """) .doTest(); } @@ -579,22 +627,24 @@ public void enclosingSuperAccess() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class A {", - " final Object lock = new Object();", - " @GuardedBy(\"lock\") boolean flag = false;", - "}", - "class B extends A {", - " void m() {", - " new Object() {", - " @GuardedBy(\"lock\")", - " void n() {", - " flag = true;", - " }", - " };", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class A { + final Object lock = new Object(); + @GuardedBy("lock") boolean flag = false; + } + class B extends A { + void m() { + new Object() { + @GuardedBy("lock") + void n() { + flag = true; + } + }; + } + } + """) .doTest(); } @@ -603,17 +653,19 @@ public void superAccess_this() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class A {", - " final Object lock = new Object();", - " @GuardedBy(\"this\") boolean flag = false;", - "}", - "class B extends A {", - " synchronized void m() {", - " flag = true;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class A { + final Object lock = new Object(); + @GuardedBy("this") boolean flag = false; + } + class B extends A { + synchronized void m() { + flag = true; + } + } + """) .doTest(); } @@ -622,22 +674,24 @@ public void superAccess_lock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class A {", - " final Object lock = new Object();", - " @GuardedBy(\"lock\") boolean flag = false;", - "}", - "class B extends A {", - " void m() {", - " synchronized (lock) {", - " flag = true;", - " }", - " synchronized (this.lock) {", - " flag = true;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class A { + final Object lock = new Object(); + @GuardedBy("lock") boolean flag = false; + } + class B extends A { + void m() { + synchronized (lock) { + flag = true; + } + synchronized (this.lock) { + flag = true; + } + } + } + """) .doTest(); } @@ -646,22 +700,24 @@ public void superAccess_staticLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class A {", - " static final Object lock = new Object();", - " @GuardedBy(\"lock\") static boolean flag = false;", - "}", - "class B extends A {", - " void m() {", - " synchronized (A.lock) {", - " flag = true;", - " }", - " synchronized (B.lock) {", - " flag = true;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class A { + static final Object lock = new Object(); + @GuardedBy("lock") static boolean flag = false; + } + class B extends A { + void m() { + synchronized (A.lock) { + flag = true; + } + synchronized (B.lock) { + flag = true; + } + } + } + """) .doTest(); } @@ -670,28 +726,30 @@ public void otherClass_bad_staticLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class A {", - " static final Object lock = new Object();", - " @GuardedBy(\"lock\") static boolean flag = false;", - "}", - "class B {", - " static final Object lock = new Object();", - " @GuardedBy(\"lock\") static boolean flag = false;", - " void m() {", - " synchronized (B.lock) {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'A.lock'", - " A.flag = true;", - " }", - " synchronized (A.lock) {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'B.lock'", - " B.flag = true;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class A { + static final Object lock = new Object(); + @GuardedBy("lock") static boolean flag = false; + } + class B { + static final Object lock = new Object(); + @GuardedBy("lock") static boolean flag = false; + void m() { + synchronized (B.lock) { + // BUG: Diagnostic contains: + // should be guarded by 'A.lock' + A.flag = true; + } + synchronized (A.lock) { + // BUG: Diagnostic contains: + // should be guarded by 'B.lock' + B.flag = true; + } + } + } + """) .doTest(); } @@ -700,28 +758,30 @@ public void otherClass_bad_staticLock_alsoSub() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class A {", - " static final Object lock = new Object();", - " @GuardedBy(\"lock\") static boolean flag = false;", - "}", - "class B extends A {", - " static final Object lock = new Object();", - " @GuardedBy(\"lock\") static boolean flag = false;", - " void m() {", - " synchronized (B.lock) {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'A.lock'", - " A.flag = true;", - " }", - " synchronized (A.lock) {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'B.lock'", - " B.flag = true;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class A { + static final Object lock = new Object(); + @GuardedBy("lock") static boolean flag = false; + } + class B extends A { + static final Object lock = new Object(); + @GuardedBy("lock") static boolean flag = false; + void m() { + synchronized (B.lock) { + // BUG: Diagnostic contains: + // should be guarded by 'A.lock' + A.flag = true; + } + synchronized (A.lock) { + // BUG: Diagnostic contains: + // should be guarded by 'B.lock' + B.flag = true; + } + } + } + """) .doTest(); } @@ -730,19 +790,21 @@ public void otherClass_staticLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class A {", - " static final Object lock = new Object();", - " @GuardedBy(\"lock\") static boolean flag = false;", - "}", - "class B {", - " void m() {", - " synchronized (A.lock) {", - " A.flag = true;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class A { + static final Object lock = new Object(); + @GuardedBy("lock") static boolean flag = false; + } + class B { + void m() { + synchronized (A.lock) { + A.flag = true; + } + } + } + """) .doTest(); } @@ -751,26 +813,28 @@ public void instanceAccess_instanceGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class InstanceAccess_InstanceGuard {", - " class A {", - " final Object lock = new Object();", - " @GuardedBy(\"lock\")", - " int x;", - " }", - "", - "class B extends A {", - " void m() {", - " synchronized (this.lock) {", - " this.x++;", - " }", - " // BUG: Diagnostic contains:", - " // should be guarded by 'this.lock'", - " this.x++;", - " }", - "}", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class InstanceAccess_InstanceGuard { + class A { + final Object lock = new Object(); + @GuardedBy("lock") + int x; + } + + class B extends A { + void m() { + synchronized (this.lock) { + this.x++; + } + // BUG: Diagnostic contains: + // should be guarded by 'this.lock' + this.x++; + } + } + } + """) .doTest(); } @@ -779,25 +843,27 @@ public void instanceAccess_lexicalGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class InstanceAccess_LexicalGuard {", - " class Outer {", - " final Object lock = new Object();", - " class Inner {", - " @GuardedBy(\"lock\")", - " int x;", - " void m() {", - " synchronized (Outer.this.lock) {", - " this.x++;", - " }", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Outer.this.lock'", - " this.x++;", - " }", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class InstanceAccess_LexicalGuard { + class Outer { + final Object lock = new Object(); + class Inner { + @GuardedBy("lock") + int x; + void m() { + synchronized (Outer.this.lock) { + this.x++; + } + // BUG: Diagnostic contains: + // should be guarded by 'Outer.this.lock' + this.x++; + } + } + } + } + """) .doTest(); } @@ -806,25 +872,27 @@ public void lexicalAccess_instanceGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class LexicalAccess_InstanceGuard {", - " class Outer {", - " final Object lock = new Object();", - " @GuardedBy(\"lock\")", - " int x;", - " class Inner {", - " void m() {", - " synchronized (Outer.this.lock) {", - " Outer.this.x++;", - " }", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Outer.this.lock'", - " Outer.this.x++;", - " }", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class LexicalAccess_InstanceGuard { + class Outer { + final Object lock = new Object(); + @GuardedBy("lock") + int x; + class Inner { + void m() { + synchronized (Outer.this.lock) { + Outer.this.x++; + } + // BUG: Diagnostic contains: + // should be guarded by 'Outer.this.lock' + Outer.this.x++; + } + } + } + } + """) .doTest(); } @@ -833,27 +901,29 @@ public void lexicalAccess_lexicalGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class LexicalAccess_LexicalGuard {", - " class Outer {", - " final Object lock = new Object();", - " class Inner {", - " @GuardedBy(\"lock\")", - " int x;", - " class InnerMost {", - " void m() {", - " synchronized (Outer.this.lock) {", - " Inner.this.x++;", - " }", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Outer.this.lock'", - " Inner.this.x++;", - " }", - " }", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class LexicalAccess_LexicalGuard { + class Outer { + final Object lock = new Object(); + class Inner { + @GuardedBy("lock") + int x; + class InnerMost { + void m() { + synchronized (Outer.this.lock) { + Inner.this.x++; + } + // BUG: Diagnostic contains: + // should be guarded by 'Outer.this.lock' + Inner.this.x++; + } + } + } + } + } + """) .doTest(); } @@ -862,24 +932,26 @@ public void instanceAccess_thisGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class InstanceAccess_ThisGuard {", - " class A {", - " @GuardedBy(\"this\")", - " int x;", - " }", - " class B extends A {", - " void m() {", - " synchronized (this) {", - " this.x++;", - " }", - " // BUG: Diagnostic contains:", - " // should be guarded by 'this'", - " this.x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class InstanceAccess_ThisGuard { + class A { + @GuardedBy("this") + int x; + } + class B extends A { + void m() { + synchronized (this) { + this.x++; + } + // BUG: Diagnostic contains: + // should be guarded by 'this' + this.x++; + } + } + } + """) .doTest(); } @@ -888,24 +960,26 @@ public void instanceAccess_namedThisGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class InstanceAccess_NamedThisGuard {", - " class Outer {", - " class Inner {", - " @GuardedBy(\"Outer.this\")", - " int x;", - " void m() {", - " synchronized (Outer.this) {", - " x++;", - " }", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Outer.this'", - " x++;", - " }", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class InstanceAccess_NamedThisGuard { + class Outer { + class Inner { + @GuardedBy("Outer.this") + int x; + void m() { + synchronized (Outer.this) { + x++; + } + // BUG: Diagnostic contains: + // should be guarded by 'Outer.this' + x++; + } + } + } + } + """) .doTest(); } @@ -914,24 +988,26 @@ public void lexicalAccess_thisGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class LexicalAccess_ThisGuard {", - " class Outer {", - " @GuardedBy(\"this\")", - " int x;", - " class Inner {", - " void m() {", - " synchronized (Outer.this) {", - " Outer.this.x++;", - " }", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Outer.this'", - " Outer.this.x++;", - " }", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class LexicalAccess_ThisGuard { + class Outer { + @GuardedBy("this") + int x; + class Inner { + void m() { + synchronized (Outer.this) { + Outer.this.x++; + } + // BUG: Diagnostic contains: + // should be guarded by 'Outer.this' + Outer.this.x++; + } + } + } + } + """) .doTest(); } @@ -940,26 +1016,28 @@ public void lexicalAccess_namedThisGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class LexicalAccess_NamedThisGuard {", - " class Outer {", - " class Inner {", - " @GuardedBy(\"Outer.this\")", - " int x;", - " class InnerMost {", - " void m() {", - " synchronized (Outer.this) {", - " Inner.this.x++;", - " }", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Outer.this'", - " Inner.this.x++;", - " }", - " }", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class LexicalAccess_NamedThisGuard { + class Outer { + class Inner { + @GuardedBy("Outer.this") + int x; + class InnerMost { + void m() { + synchronized (Outer.this) { + Inner.this.x++; + } + // BUG: Diagnostic contains: + // should be guarded by 'Outer.this' + Inner.this.x++; + } + } + } + } + } + """) .doTest(); } @@ -971,16 +1049,18 @@ public void complexLockExpression() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "class ComplexLockExpression {", - " final Object[] xs = {};", - " final int[] ys = {};", - " void m(int i) {", - " synchronized (xs[i]) {", - " ys[i]++;", - " }", - " }", - "}") + """ + package threadsafety; + class ComplexLockExpression { + final Object[] xs = {}; + final int[] ys = {}; + void m(int i) { + synchronized (xs[i]) { + ys[i]++; + } + } + } + """) .doTest(); } @@ -989,22 +1069,23 @@ public void wrongInnerClassInstance() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class WrongInnerClassInstance {", - " final Object lock = new Object();", - " class Inner {", - " @GuardedBy(\"lock\") int x = 0;", - " void m(Inner i) {", - " synchronized (WrongInnerClassInstance.this.lock) {", - " // BUG: Diagnostic contains:", - " // guarded by 'lock' in enclosing instance" - + " 'threadsafety.WrongInnerClassInstance' of 'i'", - " i.x++;", - " }", - " }", - " }", - "}") + """ +package threadsafety; +import javax.annotation.concurrent.GuardedBy; +class WrongInnerClassInstance { + final Object lock = new Object(); + class Inner { + @GuardedBy("lock") int x = 0; + void m(Inner i) { + synchronized (WrongInnerClassInstance.this.lock) { + // BUG: Diagnostic contains: + // guarded by 'lock' in enclosing instance 'threadsafety.WrongInnerClassInstance' of 'i' + i.x++; + } + } + } +} +""") .doTest(); } @@ -1016,30 +1097,32 @@ public void tryWithResources() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " Lock lock;", - " @GuardedBy(\"lock\")", - " int x;", - " static class LockCloser implements AutoCloseable {", - " Lock lock;", - " LockCloser(Lock lock) {", - " this.lock = lock;", - " this.lock.lock();", - " }", - " @Override", - " public void close() throws Exception {", - " lock.unlock();", - " }", - " }", - " void m() throws Exception {", - " try (LockCloser _ = new LockCloser(lock)) {", - " x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.locks.Lock; + class Test { + Lock lock; + @GuardedBy("lock") + int x; + static class LockCloser implements AutoCloseable { + Lock lock; + LockCloser(Lock lock) { + this.lock = lock; + this.lock.lock(); + } + @Override + public void close() throws Exception { + lock.unlock(); + } + } + void m() throws Exception { + try (LockCloser _ = new LockCloser(lock)) { + x++; + } + } + } + """) .doTest(); } @@ -1048,39 +1131,41 @@ public void tryWithResources_resourceVariables() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " Lock lock;", - " @GuardedBy(\"lock\")", - " int x;", - " void m(AutoCloseable c) throws Exception {", - " try (AutoCloseable unused = c) {", - " // BUG: Diagnostic contains:", - " x++;", - " } catch (Exception e) {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'this.lock'", - " x++;", - " throw e;", - " } finally {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'this.lock'", - " x++;", - " }", - " }", - "", - " void n(AutoCloseable c) throws Exception {", - " lock.lock();", - " try (AutoCloseable unused = c) {", - " } catch (Exception e) {", - " x++;", - " } finally {", - " lock.unlock();", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.locks.Lock; + class Test { + Lock lock; + @GuardedBy("lock") + int x; + void m(AutoCloseable c) throws Exception { + try (AutoCloseable unused = c) { + // BUG: Diagnostic contains: + x++; + } catch (Exception e) { + // BUG: Diagnostic contains: + // should be guarded by 'this.lock' + x++; + throw e; + } finally { + // BUG: Diagnostic contains: + // should be guarded by 'this.lock' + x++; + } + } + + void n(AutoCloseable c) throws Exception { + lock.lock(); + try (AutoCloseable unused = c) { + } catch (Exception e) { + x++; + } finally { + lock.unlock(); + } + } + } + """) .doTest(); } @@ -1089,27 +1174,29 @@ public void lexicalScopingExampleOne() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Transaction {", - " @GuardedBy(\"this\")", - " int x;", - " interface Handler {", - " void apply();", - " }", - " public void handle() {", - " runHandler(new Handler() {", - " public void apply() {", - " // BUG: Diagnostic contains:", - " // should be guarded by 'Transaction.this'", - " x++;", - " }", - " });", - " }", - " private synchronized void runHandler(Handler handler) {", - " handler.apply();", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Transaction { + @GuardedBy("this") + int x; + interface Handler { + void apply(); + } + public void handle() { + runHandler(new Handler() { + public void apply() { + // BUG: Diagnostic contains: + // should be guarded by 'Transaction.this' + x++; + } + }); + } + private synchronized void runHandler(Handler handler) { + handler.apply(); + } + } + """) .doTest(); } @@ -1119,27 +1206,29 @@ public void lexicalScopingExampleTwo() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Transaction {", - " @GuardedBy(\"this\")", - " int x;", - " interface Handler {", - " void apply();", - " }", - " public void handle() {", - " runHandler(new Handler() {", - " @GuardedBy(\"Transaction.this\")", - " public void apply() {", - " x++;", - " }", - " });", - " }", - " private synchronized void runHandler(Handler handler) {", - " // This isn't safe...", - " handler.apply();", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Transaction { + @GuardedBy("this") + int x; + interface Handler { + void apply(); + } + public void handle() { + runHandler(new Handler() { + @GuardedBy("Transaction.this") + public void apply() { + x++; + } + }); + } + private synchronized void runHandler(Handler handler) { + // This isn't safe... + handler.apply(); + } + } + """) .doTest(); } @@ -1148,21 +1237,23 @@ public void aliasing() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.List;", - "import java.util.ArrayList;", - "class Names {", - " @GuardedBy(\"this\")", - " List names = new ArrayList<>();", - " public void addName(String name) {", - " List copyOfNames;", - " synchronized (this) {", - " copyOfNames = names; // OK: access of 'names' guarded by 'this'", - " }", - " copyOfNames.add(name); // should be an error: this access is not thread-safe!", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.List; + import java.util.ArrayList; + class Names { + @GuardedBy("this") + List names = new ArrayList<>(); + public void addName(String name) { + List copyOfNames; + synchronized (this) { + copyOfNames = names; // OK: access of 'names' guarded by 'this' + } + copyOfNames.add(name); // should be an error: this access is not thread-safe! + } + } + """) .doTest(); } @@ -1171,21 +1262,23 @@ public void monitorGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import com.google.common.util.concurrent.Monitor;", - "import java.util.List;", - "import java.util.ArrayList;", - "class Test {", - " final Monitor monitor = new Monitor();", - " @GuardedBy(\"monitor\") int x;", - " final Monitor.Guard guard = new Monitor.Guard(monitor) {", - " @Override public boolean isSatisfied() {", - " x++;", - " return true;", - " }", - " };", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import com.google.common.util.concurrent.Monitor; + import java.util.List; + import java.util.ArrayList; + class Test { + final Monitor monitor = new Monitor(); + @GuardedBy("monitor") int x; + final Monitor.Guard guard = new Monitor.Guard(monitor) { + @Override public boolean isSatisfied() { + x++; + return true; + } + }; + } + """) .doTest(); } @@ -1194,28 +1287,30 @@ public void semaphore() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.Semaphore;", - "class Test {", - " final Semaphore semaphore = null;", - " @GuardedBy(\"semaphore\")", - " int x;", - " void m() throws InterruptedException {", - " semaphore.acquire();", - " // BUG: Diagnostic contains:", - " // access should be guarded by 'this.semaphore'", - " x++;", - " try {", - " x++;", - " } finally {", - " semaphore.release();", - " }", - " // BUG: Diagnostic contains:", - " // access should be guarded by 'this.semaphore'", - " x++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.Semaphore; + class Test { + final Semaphore semaphore = null; + @GuardedBy("semaphore") + int x; + void m() throws InterruptedException { + semaphore.acquire(); + // BUG: Diagnostic contains: + // access should be guarded by 'this.semaphore' + x++; + try { + x++; + } finally { + semaphore.release(); + } + // BUG: Diagnostic contains: + // access should be guarded by 'this.semaphore' + x++; + } + } + """) .doTest(); } @@ -1246,18 +1341,20 @@ public void suppressLocalVariable() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " final Lock lock = null;", - " @GuardedBy(\"lock\")", - " int x;", - " void m() {", - " @SuppressWarnings(\"GuardedBy\")", - " int z = x++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import java.util.concurrent.locks.Lock; + class Test { + final Lock lock = null; + @GuardedBy("lock") + int x; + void m() { + @SuppressWarnings("GuardedBy") + int z = x++; + } + } + """) .doTest(); } @@ -1267,21 +1364,23 @@ public void enclosingBlockScope() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " public final Object mu = new Object();", - " @GuardedBy(\"mu\") int x = 1;", - " {", - " new Object() {", - " void f() {", - " synchronized (mu) {", - " x++;", - " }", - " }", - " };", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + public final Object mu = new Object(); + @GuardedBy("mu") int x = 1; + { + new Object() { + void f() { + synchronized (mu) { + x++; + } + } + }; + } + } + """) .doTest(); } @@ -1291,25 +1390,29 @@ public void qualifiedType() { compilationHelper .addSourceLines( "lib/Lib.java", - "package lib;", - "public class Lib {", - " public static class Inner {", - " public static final Object mu = new Object();", - " }", - "}") - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " public final Object mu = new Object();", - " @GuardedBy(\"lib.Lib.Inner.mu\") int x = 1;", - " void f() {", - " synchronized (lib.Lib.Inner.mu) {", - " x++;", - " }", - " }", - "}") + """ + package lib; + public class Lib { + public static class Inner { + public static final Object mu = new Object(); + } + } + """) + .addSourceLines( + "threadsafety/Test.java", + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + public final Object mu = new Object(); + @GuardedBy("lib.Lib.Inner.mu") int x = 1; + void f() { + synchronized (lib.Lib.Inner.mu) { + x++; + } + } + } + """) .doTest(); } @@ -1319,26 +1422,30 @@ public void innerClassTypeQualifier() { compilationHelper .addSourceLines( "lib/Lib.java", - "package lib;", - "public class Lib {", - " public static class Inner {", - " public static final Object mu = new Object();", - " }", - "}") - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import lib.Lib;", - "public class Test {", - " public final Object mu = new Object();", - " @GuardedBy(\"Lib.Inner.mu\") int x = 1;", - " void f() {", - " synchronized (Lib.Inner.mu) {", - " x++;", - " }", - " }", - "}") + """ + package lib; + public class Lib { + public static class Inner { + public static final Object mu = new Object(); + } + } + """) + .addSourceLines( + "threadsafety/Test.java", + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + import lib.Lib; + public class Test { + public final Object mu = new Object(); + @GuardedBy("Lib.Inner.mu") int x = 1; + void f() { + synchronized (Lib.Inner.mu) { + x++; + } + } + } + """) .doTest(); } @@ -1347,21 +1454,23 @@ public void instanceInitializersAreUnchecked() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " public final Object mu1 = new Object();", - " public final Object mu2 = new Object();", - " @GuardedBy(\"mu1\") int x = 1;", - " {", - " synchronized (mu2) {", - " x++;", - " }", - " synchronized (mu1) {", - " x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + public final Object mu1 = new Object(); + public final Object mu2 = new Object(); + @GuardedBy("mu1") int x = 1; + { + synchronized (mu2) { + x++; + } + synchronized (mu1) { + x++; + } + } + } + """) .doTest(); } @@ -1370,21 +1479,23 @@ public void classInitializersAreUnchecked() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " public static final Object mu1 = new Object();", - " public static final Object mu2 = new Object();", - " @GuardedBy(\"mu1\") static int x = 1;", - " static {", - " synchronized (mu2) {", - " x++;", - " }", - " synchronized (mu1) {", - " x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + public static final Object mu1 = new Object(); + public static final Object mu2 = new Object(); + @GuardedBy("mu1") static int x = 1; + static { + synchronized (mu2) { + x++; + } + synchronized (mu1) { + x++; + } + } + } + """) .doTest(); } @@ -1393,13 +1504,15 @@ public void staticFieldInitializersAreUnchecked() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " public static final Object mu = new Object();", - " @GuardedBy(\"mu\") static int x0 = 1;", - " static int x1 = x0++;", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + public static final Object mu = new Object(); + @GuardedBy("mu") static int x0 = 1; + static int x1 = x0++; + } + """) .doTest(); } @@ -1408,13 +1521,15 @@ public void instanceFieldInitializersAreUnchecked() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " public final Object mu = new Object();", - " @GuardedBy(\"mu\") int x0 = 1;", - " int x1 = x0++;", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + public final Object mu = new Object(); + @GuardedBy("mu") int x0 = 1; + int x1 = x0++; + } + """) .doTest(); } @@ -1423,27 +1538,29 @@ public void innerClassMethod() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " public final Object mu = new Object();", - " class Inner {", - " @GuardedBy(\"mu\") int x;", - " @GuardedBy(\"Test.this\") int y;", - " }", - " void f(Inner i) {", - " synchronized (mu) {", - " // BUG: Diagnostic contains:", - " // guarded by 'mu' in enclosing instance 'threadsafety.Test' of 'i'", - " i.x++;", - " }", - " }", - " synchronized void g(Inner i) {", - " // BUG: Diagnostic contains:", - " // guarded by enclosing instance 'threadsafety.Test' of 'i'", - " i.y++;", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + public final Object mu = new Object(); + class Inner { + @GuardedBy("mu") int x; + @GuardedBy("Test.this") int y; + } + void f(Inner i) { + synchronized (mu) { + // BUG: Diagnostic contains: + // guarded by 'mu' in enclosing instance 'threadsafety.Test' of 'i' + i.x++; + } + } + synchronized void g(Inner i) { + // BUG: Diagnostic contains: + // guarded by enclosing instance 'threadsafety.Test' of 'i' + i.y++; + } + } + """) .doTest(); } @@ -1453,21 +1570,23 @@ public void innerClassInMethod() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " public final Object mu = new Object();", - " @GuardedBy(\"mu\") int i = 0;", - " void f() {", - " class Inner {", - " @GuardedBy(\"mu\") void m() {i++;}", - " }", - " Inner i = new Inner();", - " synchronized (mu) {", - " i.m();", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + public final Object mu = new Object(); + @GuardedBy("mu") int i = 0; + void f() { + class Inner { + @GuardedBy("mu") void m() {i++;} + } + Inner i = new Inner(); + synchronized (mu) { + i.m(); + } + } + } + """) .doTest(); } @@ -1476,38 +1595,40 @@ public void innerClassMethod_classBoundary() { compilationHelper .addSourceLines( "threadsafety/Outer.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Outer {", - " public final Object mu = new Object();", - " class Inner {", - " @GuardedBy(\"mu\") int x;", - " @GuardedBy(\"Outer.this\") int y;", - " }", - "}") - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " void f() {", - " Outer a = new Outer();", - " Outer b = new Outer();", - " Outer.Inner ai = a.new Inner();", - " synchronized (b.mu) {", - " // BUG: Diagnostic contains:", - " // Access should be guarded by 'mu' in enclosing instance 'threadsafety.Outer'" - + " of 'ai', which is not accessible in this scope; instead found: 'b.mu'", - " ai.x++;", - " }", - " synchronized (b) {", - " // BUG: Diagnostic contains:", - " // Access should be guarded by enclosing instance 'threadsafety.Outer' of 'ai'," - + " which is not accessible in this scope; instead found: 'b'", - " ai.y++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Outer { + public final Object mu = new Object(); + class Inner { + @GuardedBy("mu") int x; + @GuardedBy("Outer.this") int y; + } + } + """) + .addSourceLines( + "threadsafety/Test.java", + """ +package threadsafety; +import javax.annotation.concurrent.GuardedBy; +public class Test { + void f() { + Outer a = new Outer(); + Outer b = new Outer(); + Outer.Inner ai = a.new Inner(); + synchronized (b.mu) { + // BUG: Diagnostic contains: + // Access should be guarded by 'mu' in enclosing instance 'threadsafety.Outer' of 'ai', which is not accessible in this scope; instead found: 'b.mu' + ai.x++; + } + synchronized (b) { + // BUG: Diagnostic contains: + // Access should be guarded by enclosing instance 'threadsafety.Outer' of 'ai', which is not accessible in this scope; instead found: 'b' + ai.y++; + } + } +} +""") .doTest(); } @@ -1515,26 +1636,32 @@ public void innerClassMethod_classBoundary() { public void regression_b27686620() { compilationHelper .addSourceLines( - "A.java", // - "class A extends One {", - " void g() {}", - "}") + "A.java", + """ + class A extends One { + void g() {} + } + """) .addSourceLines( "B.java", - "import javax.annotation.concurrent.GuardedBy;", - "class One {", - " @GuardedBy(\"One.class\") static int x = 1;", - " static void f() { synchronized (One.class) { x++; } }", - "}", - "class Two {", - " @GuardedBy(\"Two.class\") static int x = 1;", - " static void f() { synchronized (Two.class) { x++; } }", - "}") + """ + import javax.annotation.concurrent.GuardedBy; + class One { + @GuardedBy("One.class") static int x = 1; + static void f() { synchronized (One.class) { x++; } } + } + class Two { + @GuardedBy("Two.class") static int x = 1; + static void f() { synchronized (Two.class) { x++; } } + } + """) .addSourceLines( - "C.java", // - "class B extends Two {", - " void g() {}", - "}") + "C.java", + """ + class B extends Two { + void g() {} + } + """) .doTest(); } @@ -1543,18 +1670,20 @@ public void qualifiedMethod() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " @GuardedBy(\"this\") void f() {}", - " void main() {", - " // BUG: Diagnostic contains: 'this', which could not be resolved", - " new Test().f();", - " Test t = new Test();", - " // BUG: Diagnostic contains: guarded by 't'", - " t.f();", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + @GuardedBy("this") void f() {} + void main() { + // BUG: Diagnostic contains: 'this', which could not be resolved + new Test().f(); + Test t = new Test(); + // BUG: Diagnostic contains: guarded by 't' + t.f(); + } + } + """) .doTest(); } @@ -1563,22 +1692,22 @@ public void qualifiedMethodWrongThis_causesFinding_whenMatchOnErrorsFlagNotSet() CompilationTestHelper.newInstance(GuardedByChecker.class, getClass()) .addSourceLines( "MemoryAllocatedInfoJava.java", - "import javax.annotation.concurrent.GuardedBy;", - "public class MemoryAllocatedInfoJava {", - " private static final class AllocationStats {", - " @GuardedBy(\"MemoryAllocatedInfoJava.this\")", - " void addAllocation(long size) {}", - " }", - " public void addStackTrace(long size) {", - " synchronized (this) {", - " AllocationStats stat = new AllocationStats();", - " // BUG: Diagnostic contains: Access should be guarded by enclosing instance " - + "'MemoryAllocatedInfoJava' of 'stat', which is not accessible in this scope; " - + "instead found: 'this'", - " stat.addAllocation(size);", - " }", - " }", - "}") + """ +import javax.annotation.concurrent.GuardedBy; +public class MemoryAllocatedInfoJava { + private static final class AllocationStats { + @GuardedBy("MemoryAllocatedInfoJava.this") + void addAllocation(long size) {} + } + public void addStackTrace(long size) { + synchronized (this) { + AllocationStats stat = new AllocationStats(); + // BUG: Diagnostic contains: Access should be guarded by enclosing instance 'MemoryAllocatedInfoJava' of 'stat', which is not accessible in this scope; instead found: 'this' + stat.addAllocation(size); + } + } +} +""") .doTest(); } @@ -1591,12 +1720,14 @@ public void noSuchMethod() { "public class Foo {}") .addSourceLines( "Test.java", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " Foo foo;", - " // BUG: Diagnostic contains: could not resolve guard", - " @GuardedBy(\"foo.get()\") Object o = null;", - "}") + """ + import javax.annotation.concurrent.GuardedBy; + public class Test { + Foo foo; + // BUG: Diagnostic contains: could not resolve guard + @GuardedBy("foo.get()") Object o = null; + } + """) .doTest(); } @@ -1606,16 +1737,18 @@ public void lambda() { compilationHelper .addSourceLines( "Test.java", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " @GuardedBy(\"this\") int x;", - " synchronized void f() {", - " Runnable r = () -> {", - " // BUG: Diagnostic contains: should be guarded by 'this',", - " x++;", - " };", - " }", - "}") + """ + import javax.annotation.concurrent.GuardedBy; + public class Test { + @GuardedBy("this") int x; + synchronized void f() { + Runnable r = () -> { + // BUG: Diagnostic contains: should be guarded by 'this', + x++; + }; + } + } + """) .doTest(); } @@ -1623,31 +1756,35 @@ public void lambda() { public void multipleLocks() { compilationHelper .addSourceLines( - "GuardedBy.java", // - "@interface GuardedBy {", - " String[] value() default {};", - "}") + "GuardedBy.java", + """ + @interface GuardedBy { + String[] value() default {}; + } + """) .addSourceLines( "Test.java", - "public class Test {", - " private final Object mu = new Object();", - " @GuardedBy({\"this\", \"mu\"}) int x;", - " void f() {", - " synchronized (this) {", - " synchronized (mu) {", - " x++;", - " }", - " }", - " synchronized (this) {", - " // BUG: Diagnostic contains: should be guarded by 'this.mu'", - " x++;", - " }", - " synchronized (mu) {", - " // BUG: Diagnostic contains: should be guarded by 'this'", - " x++;", - " }", - " }", - "}") + """ + public class Test { + private final Object mu = new Object(); + @GuardedBy({"this", "mu"}) int x; + void f() { + synchronized (this) { + synchronized (mu) { + x++; + } + } + synchronized (this) { + // BUG: Diagnostic contains: should be guarded by 'this.mu' + x++; + } + synchronized (mu) { + // BUG: Diagnostic contains: should be guarded by 'this' + x++; + } + } + } + """) .doTest(); } @@ -1658,21 +1795,23 @@ public void staticMemberClass_enclosingInstanceLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " final Object mu = new Object();", - " private static final class Baz {", - " // BUG: Diagnostic contains: could not resolve guard", - " @GuardedBy(\"mu\") int x;", - " }", - " public void m(Baz b) {", - " synchronized (mu) {", - " // BUG: Diagnostic contains: 'mu', which could not be resolved", - " b.x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + final Object mu = new Object(); + private static final class Baz { + // BUG: Diagnostic contains: could not resolve guard + @GuardedBy("mu") int x; + } + public void m(Baz b) { + synchronized (mu) { + // BUG: Diagnostic contains: 'mu', which could not be resolved + b.x++; + } + } + } + """) .doTest(); } @@ -1683,19 +1822,21 @@ public void staticMemberClass_staticOuterClassLock() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "public class Test {", - " static final Object mu = new Object();", - " private static final class Baz {", - " @GuardedBy(\"mu\") int x;", - " }", - " public void m(Baz b) {", - " synchronized (mu) {", - " b.x++;", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + public class Test { + static final Object mu = new Object(); + private static final class Baz { + @GuardedBy("mu") int x; + } + public void m(Baz b) { + synchronized (mu) { + b.x++; + } + } + } + """) .doTest(); } @@ -1704,23 +1845,27 @@ public void newClassBase() { compilationHelper .addSourceLines( "Foo.java", - "import javax.annotation.concurrent.GuardedBy;", - "public class Foo {", - " private final Object mu = new Object();", - " @GuardedBy(\"mu\") int x;", - "}") + """ + import javax.annotation.concurrent.GuardedBy; + public class Foo { + private final Object mu = new Object(); + @GuardedBy("mu") int x; + } + """) .addSourceLines( "Bar.java", - "public class Bar {", - " void bar (Foo f) {", - " // BUG: Diagnostic contains: should be guarded by 'f.mu'", - " f.x = 10;", - " }", - " void bar () {", - " // BUG: Diagnostic contains: should be guarded by 'mu'", - " new Foo().x = 11;", - " }", - "}") + """ + public class Bar { + void bar (Foo f) { + // BUG: Diagnostic contains: should be guarded by 'f.mu' + f.x = 10; + } + void bar () { + // BUG: Diagnostic contains: should be guarded by 'mu' + new Foo().x = 11; + } + } + """) .doTest(); } @@ -1729,22 +1874,24 @@ public void suppressionOnMethod() { compilationHelper .addSourceLines( "Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " final Object lock = null;", - " void foo() {", - " class Foo extends Object {", - " @GuardedBy(\"lock\") int x;", - " @SuppressWarnings(\"GuardedBy\")", - " void m() {", - " synchronized (lock) {", - " int z = x++;", - " }", - " }", - " }", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + final Object lock = null; + void foo() { + class Foo extends Object { + @GuardedBy("lock") int x; + @SuppressWarnings("GuardedBy") + void m() { + synchronized (lock) { + int z = x++; + } + } + } + } + } + """) .doTest(); } @@ -1753,22 +1900,26 @@ public void missingGuard() { compilationHelper .addSourceLines( "threadsafety/Lib.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "@SuppressWarnings(\"GuardedBy\")", - "class Lib {", - " @GuardedBy(\"lock\")", - " public void doSomething() {}", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + @SuppressWarnings("GuardedBy") + class Lib { + @GuardedBy("lock") + public void doSomething() {} + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "class Test {", - " void m(Lib lib) {", - " // BUG: Diagnostic contains: 'lock', which could not be resolved", - " lib.doSomething();", - " }", - "}") + """ + package threadsafety; + class Test { + void m(Lib lib) { + // BUG: Diagnostic contains: 'lock', which could not be resolved + lib.doSomething(); + } + } + """) .doTest(); } @@ -1777,45 +1928,46 @@ public void parameterGuard() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "import javax.annotation.concurrent.GuardedBy;", - "class Work {", - " final Object lock = new Object();", - " Object getLock() {", - " return lock;", - " }", - " @GuardedBy(\"getLock()\")", - " void workStarted() {", - " }", - "}", - "class Worker {", - " @GuardedBy(\"work.getLock()\")", - " void f(Work work) {", - " work.workStarted(); // ok", - " }", - " // BUG: Diagnostic contains: could not resolve guard", - " @GuardedBy(\"work2.getLock()\") void g() {}", - " @GuardedBy(\"a.getLock()\")", - " void g(Work a, Work b) {", - " a.workStarted(); // ok", - " // BUG: Diagnostic contains: should be guarded by 'b.getLock()'; instead found:" - + " 'a.getLock()'", - " b.workStarted();", - " }", - "}", - "abstract class Test {", - " abstract Work getWork();", - " void t(Worker worker, Work work) {", - " synchronized(work.getLock()) {", - " worker.f(work);", - " }", - " synchronized(getWork().getLock()) {", - " // BUG: Diagnostic contains: guarded by 'work.getLock()'", - " worker.f(getWork());", - " }", - " // BUG: Diagnostic contains: guarded by 'work.getLock()'", - " worker.f(work);", - " }", - "}") + """ +import javax.annotation.concurrent.GuardedBy; +class Work { + final Object lock = new Object(); + Object getLock() { + return lock; + } + @GuardedBy("getLock()") + void workStarted() { + } +} +class Worker { + @GuardedBy("work.getLock()") + void f(Work work) { + work.workStarted(); // ok + } + // BUG: Diagnostic contains: could not resolve guard + @GuardedBy("work2.getLock()") void g() {} + @GuardedBy("a.getLock()") + void g(Work a, Work b) { + a.workStarted(); // ok + // BUG: Diagnostic contains: should be guarded by 'b.getLock()'; instead found: 'a.getLock()' + b.workStarted(); + } +} +abstract class Test { + abstract Work getWork(); + void t(Worker worker, Work work) { + synchronized(work.getLock()) { + worker.f(work); + } + synchronized(getWork().getLock()) { + // BUG: Diagnostic contains: guarded by 'work.getLock()' + worker.f(getWork()); + } + // BUG: Diagnostic contains: guarded by 'work.getLock()' + worker.f(work); + } +} +""") .doTest(); } @@ -1824,25 +1976,27 @@ public void parameterGuardNegative() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "import javax.annotation.concurrent.GuardedBy;", - "class Work {", - " final Object lock = new Object();", - " Object getLock() {", - " return lock;", - " }", - "}", - "class Worker {", - " @GuardedBy(\"work.getLock()\")", - " void f(Work work) {", - " }", - "}", - "class Test {", - " void t(Worker worker, Work work) {", - " synchronized(work.getLock()) {", - " worker.f(work);", - " }", - " }", - "}") + """ + import javax.annotation.concurrent.GuardedBy; + class Work { + final Object lock = new Object(); + Object getLock() { + return lock; + } + } + class Worker { + @GuardedBy("work.getLock()") + void f(Work work) { + } + } + class Test { + void t(Worker worker, Work work) { + synchronized(work.getLock()) { + worker.f(work); + } + } + } + """) .doTest(); } @@ -1851,24 +2005,26 @@ public void parameterGuardNegativeSimpleName() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "import javax.annotation.concurrent.GuardedBy;", - "class Work {", - " final Object lock = new Object();", - " Object getLock() {", - " return lock;", - " }", - "}", - "class Worker {", - " @GuardedBy(\"work.getLock()\")", - " void f(Work work) {", - " }", - " void g() {", - " Work work = new Work();", - " synchronized(work.getLock()) {", - " f(work);", - " }", - " }", - "}") + """ + import javax.annotation.concurrent.GuardedBy; + class Work { + final Object lock = new Object(); + Object getLock() { + return lock; + } + } + class Worker { + @GuardedBy("work.getLock()") + void f(Work work) { + } + void g() { + Work work = new Work(); + synchronized(work.getLock()) { + f(work); + } + } + } + """) .doTest(); } @@ -1877,20 +2033,22 @@ public void varargsArity() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"xs.toString()\")", - " void f(int x, Object... xs) {", - " }", - " void g() {", - " Object[] xs = null;", - " synchronized(xs.toString()) {", - " f(0, xs);", - " }", - " // BUG: Diagnostic contains:", - " f(0);", - " }", - "}") + """ + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("xs.toString()") + void f(int x, Object... xs) { + } + void g() { + Object[] xs = null; + synchronized(xs.toString()) { + f(0, xs); + } + // BUG: Diagnostic contains: + f(0); + } + } + """) .doTest(); } @@ -1899,22 +2057,24 @@ public void immediateLambdas() { compilationHelper .addSourceLines( "Test.java", - "import java.util.ArrayList;", - "import java.util.List;", - "import java.util.Optional;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"this\") private final List xs = new ArrayList<>();", - " @GuardedBy(\"ys\") private final List ys = new ArrayList<>();", - " public synchronized void add(Optional x) {", - " x.ifPresent(y -> xs.add(y));", - " x.ifPresent(xs::add);", - " // BUG: Diagnostic contains:", - " x.ifPresent(y -> ys.add(y));", - " // BUG: Diagnostic contains:", - " x.ifPresent(ys::add);", - " }", - "}") + """ + import java.util.ArrayList; + import java.util.List; + import java.util.Optional; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("this") private final List xs = new ArrayList<>(); + @GuardedBy("ys") private final List ys = new ArrayList<>(); + public synchronized void add(Optional x) { + x.ifPresent(y -> xs.add(y)); + x.ifPresent(xs::add); + // BUG: Diagnostic contains: + x.ifPresent(y -> ys.add(y)); + // BUG: Diagnostic contains: + x.ifPresent(ys::add); + } + } + """) .doTest(); } @@ -1923,19 +2083,21 @@ public void methodReferences_shouldBeFlagged() { compilationHelper .addSourceLines( "Test.java", - "import java.util.ArrayList;", - "import java.util.List;", - "import java.util.Optional;", - "import java.util.function.Predicate;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"this\") private final List xs = new ArrayList<>();", - " private final List> preds = new ArrayList<>();", - " public synchronized void test() {", - " // BUG: Diagnostic contains:", - " preds.add(xs::contains);", - " }", - "}") + """ + import java.util.ArrayList; + import java.util.List; + import java.util.Optional; + import java.util.function.Predicate; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("this") private final List xs = new ArrayList<>(); + private final List> preds = new ArrayList<>(); + public synchronized void test() { + // BUG: Diagnostic contains: + preds.add(xs::contains); + } + } + """) .doTest(); } @@ -1944,23 +2106,25 @@ public void methodReference_referencedMethodIsFlagged() { compilationHelper .addSourceLines( "Test.java", - "import java.util.ArrayList;", - "import java.util.List;", - "import java.util.Optional;", - "import java.util.function.Predicate;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " private final List> preds = new ArrayList<>();", - " public synchronized void test() {", - " Optional.of(\"foo\").ifPresent(this::frobnicate);", - " // BUG: Diagnostic contains: should be guarded by", - " preds.add(this::frobnicate);", - " }", - " @GuardedBy(\"this\")", - " public boolean frobnicate(String x) {", - " return true;", - " }", - "}") + """ + import java.util.ArrayList; + import java.util.List; + import java.util.Optional; + import java.util.function.Predicate; + import javax.annotation.concurrent.GuardedBy; + class Test { + private final List> preds = new ArrayList<>(); + public synchronized void test() { + Optional.of("foo").ifPresent(this::frobnicate); + // BUG: Diagnostic contains: should be guarded by + preds.add(this::frobnicate); + } + @GuardedBy("this") + public boolean frobnicate(String x) { + return true; + } + } + """) .doTest(); } @@ -1969,14 +2133,16 @@ public void lambdaMethodInvokedImmediately_shouldNotBeFlagged() { compilationHelper .addSourceLines( "Test.java", - "import java.util.List;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"this\") private final Object o = new Object();", - " public synchronized void test(List xs) {", - " xs.forEach(x -> o.toString());", - " }", - "}") + """ + import java.util.List; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("this") private final Object o = new Object(); + public synchronized void test(List xs) { + xs.forEach(x -> o.toString()); + } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/GuardedByValidatorTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/GuardedByValidatorTest.java index 2451365cdf5..75f7b3636e3 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/GuardedByValidatorTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/GuardedByValidatorTest.java @@ -32,16 +32,18 @@ public void positive() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: could not resolve guard", - " @GuardedBy(\"This thread\") int x;", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: could not resolve guard", - " @GuardedBy(\"This thread\") void m() {}", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: could not resolve guard + @GuardedBy("This thread") int x; + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: could not resolve guard + @GuardedBy("This thread") void m() {} + } + """) .doTest(); } @@ -50,22 +52,24 @@ public void negative() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " final Object mu = new Object();", - " class Inner {", - " @GuardedBy(\"this\") int x;", - " @GuardedBy(\"Test.this\") int p;", - " @GuardedBy(\"Test.this.mu\") int z;", - " @GuardedBy(\"this\") void m() {}", - " @GuardedBy(\"mu\") int v;", - " @GuardedBy(\"itself\") Object s_;", - " }", - " final Object o = new Object() {", - " @GuardedBy(\"mu\") int x;", - " };", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + final Object mu = new Object(); + class Inner { + @GuardedBy("this") int x; + @GuardedBy("Test.this") int p; + @GuardedBy("Test.this.mu") int z; + @GuardedBy("this") void m() {} + @GuardedBy("mu") int v; + @GuardedBy("itself") Object s_; + } + final Object o = new Object() { + @GuardedBy("mu") int x; + }; + } + """) .doTest(); } @@ -74,11 +78,13 @@ public void itself() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"itself\") Object s_;", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("itself") Object s_; + } + """) .doTest(); } @@ -87,14 +93,16 @@ public void badInstanceAccess() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " final Object instanceField = new Object();", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: could not resolve guard", - " @GuardedBy(\"Test.instanceField\") Object s_;", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + final Object instanceField = new Object(); + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: could not resolve guard + @GuardedBy("Test.instanceField") Object s_; + } + """) .doTest(); } @@ -103,13 +111,15 @@ public void className() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: could not resolve guard", - " @GuardedBy(\"Test\") Object s_;", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: could not resolve guard + @GuardedBy("Test") Object s_; + } + """) .doTest(); } @@ -118,28 +128,30 @@ public void anonymousClassTypo() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " static class Endpoint {", - " Object getLock() { return null; }", - " }", - " abstract static class Runnable {", - " private Endpoint endpoint;", - " Runnable(Endpoint endpoint) {", - " this.endpoint = endpoint;", - " }", - " abstract void run();", - " }", - " static void m(Endpoint endpoint) {", - " Runnable runnable =", - " new Runnable(endpoint) {", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: could not resolve guard", - " @GuardedBy(\"endpoint_.getLock()\") void run() {}", - " };", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + static class Endpoint { + Object getLock() { return null; } + } + abstract static class Runnable { + private Endpoint endpoint; + Runnable(Endpoint endpoint) { + this.endpoint = endpoint; + } + abstract void run(); + } + static void m(Endpoint endpoint) { + Runnable runnable = + new Runnable(endpoint) { + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: could not resolve guard + @GuardedBy("endpoint_.getLock()") void run() {} + }; + } + } + """) .doTest(); } @@ -148,28 +160,30 @@ public void anonymousClassPrivateAccess() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " static class Endpoint {", - " Object getLock() { return null; }", - " }", - " abstract static class Runnable {", - " private Endpoint endpoint;", - " Runnable(Endpoint endpoint) {", - " this.endpoint = endpoint;", - " }", - " abstract void run();", - " }", - " static void m(Endpoint endpoint) {", - " Runnable runnable =", - " new Runnable(endpoint) {", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: could not resolve guard", - " @GuardedBy(\"endpoint.getLock()\") void run() {}", - " };", - " }", - "}") + """ + package threadsafety; + import javax.annotation.concurrent.GuardedBy; + class Test { + static class Endpoint { + Object getLock() { return null; } + } + abstract static class Runnable { + private Endpoint endpoint; + Runnable(Endpoint endpoint) { + this.endpoint = endpoint; + } + abstract void run(); + } + static void m(Endpoint endpoint) { + Runnable runnable = + new Runnable(endpoint) { + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: could not resolve guard + @GuardedBy("endpoint.getLock()") void run() {} + }; + } + } + """) .doTest(); } @@ -178,13 +192,15 @@ public void staticGuardedByInstance() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: static member guarded by instance", - " @GuardedBy(\"this\") static int x;", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: static member guarded by instance + @GuardedBy("this") static int x; + } + """) .doTest(); } @@ -193,15 +209,17 @@ public void staticGuardedByInstanceMethod() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " final Object mu_ = new Object();", - " Object lock() { return mu_; }", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: static member guarded by instance", - " @GuardedBy(\"lock()\") static int x;", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + final Object mu_ = new Object(); + Object lock() { return mu_; } + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: static member guarded by instance + @GuardedBy("lock()") static int x; + } + """) .doTest(); } @@ -210,11 +228,13 @@ public void staticGuardedByStatic() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " @GuardedBy(\"Test.class\") static int x;", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + @GuardedBy("Test.class") static int x; + } + """) .doTest(); } @@ -223,16 +243,18 @@ public void nonExistantMethod() { compilationHelper .addSourceLines( "threadsafety/Test.java", - "package threadsafety.Test;", - "import javax.annotation.concurrent.GuardedBy;", - "class Test {", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: could not resolve guard", - " @GuardedBy(\"lock()\") int x;", - " // BUG: Diagnostic contains:", - " // Invalid @GuardedBy expression: could not resolve guard", - " @GuardedBy(\"lock()\") void m() {}", - "}") + """ + package threadsafety.Test; + import javax.annotation.concurrent.GuardedBy; + class Test { + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: could not resolve guard + @GuardedBy("lock()") int x; + // BUG: Diagnostic contains: + // Invalid @GuardedBy expression: could not resolve guard + @GuardedBy("lock()") void m() {} + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableCheckerTest.java index 121826b219d..9f626182004 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableCheckerTest.java @@ -41,17 +41,19 @@ public void basicFields() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class Test {", - " final int a = 42;", - " final String b = null;", - " final java.lang.String c = null;", - " final com.google.common.collect.ImmutableList d = null;", - " final ImmutableList e = null;", - " final Deprecated dep = null;", - " final Class clazz = Class.class;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class Test { + final int a = 42; + final String b = null; + final java.lang.String c = null; + final com.google.common.collect.ImmutableList d = null; + final ImmutableList e = null; + final Deprecated dep = null; + final Class clazz = Class.class; + } + """) .doTest(); } @@ -61,12 +63,13 @@ public void interfacesMutableByDefault() { .addSourceLines("I.java", "interface I {}") .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:" - + " 'I' is not annotated with @com.google.errorprone.annotations.Immutable", - " private final I i = new I() {};", - "}") + """ +import com.google.errorprone.annotations.Immutable; +@Immutable class Test { + // BUG: Diagnostic contains: 'I' is not annotated with @com.google.errorprone.annotations.Immutable + private final I i = new I() {}; +} +""") .doTest(); } @@ -75,8 +78,10 @@ public void annotationsAreImmutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable @interface Test {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable @interface Test {} + """) .doTest(); } @@ -85,19 +90,23 @@ public void customAnnotationsMightBeMutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable @interface Test {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable @interface Test {} + """) .addSourceLines( "MyTest.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.lang.annotation.Annotation;", - "@Immutable final class MyTest implements Test {", - " // BUG: Diagnostic contains: non-final", - " public Object[] xs = {};", - " public Class annotationType() {", - " return null;", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.lang.annotation.Annotation; + @Immutable final class MyTest implements Test { + // BUG: Diagnostic contains: non-final + public Object[] xs = {}; + public Class annotationType() { + return null; + } + } + """) .doTest(); } @@ -108,20 +117,24 @@ public void customImplementionsOfImplicitlyImmutableAnnotationsMustBeImmutable() .addSourceLines("Anno.java", "@interface Anno {}") .addSourceLines( "MyAnno.java", - "import java.lang.annotation.Annotation;", - "final class MyAnno implements Anno {", - " // BUG: Diagnostic contains:", - " public Object[] xs = {};", - " public Class annotationType() {", - " return null;", - " }", - "}") + """ + import java.lang.annotation.Annotation; + final class MyAnno implements Anno { + // BUG: Diagnostic contains: + public Object[] xs = {}; + public Class annotationType() { + return null; + } + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " private final Anno anno = new MyAnno();", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + private final Anno anno = new MyAnno(); + } + """) .doTest(); } @@ -130,18 +143,22 @@ public void customAnnotationsSubtype() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable @interface Test {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable @interface Test {} + """) .addSourceLines( "MyTest.java", - "import java.lang.annotation.Annotation;", - "final class MyTest implements Test {", - " // BUG: Diagnostic contains: non-final field 'xs'", - " public Object[] xs = {};", - " public Class annotationType() {", - " return null;", - " }", - "}") + """ + import java.lang.annotation.Annotation; + final class MyTest implements Test { + // BUG: Diagnostic contains: non-final field 'xs' + public Object[] xs = {}; + public Class annotationType() { + return null; + } + } + """) .doTest(); } @@ -150,11 +167,13 @@ public void annotationsDefaultToImmutable() { compilationHelper .addSourceLines( "Test.java", - "import javax.lang.model.element.ElementKind;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " private final Override override = null;", - "}") + """ + import javax.lang.model.element.ElementKind; + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + private final Override override = null; + } + """) .doTest(); } @@ -163,11 +182,13 @@ public void enumsDefaultToImmutable() { compilationHelper .addSourceLines( "Test.java", - "import javax.lang.model.element.ElementKind;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " private final ElementKind ek = null;", - "}") + """ + import javax.lang.model.element.ElementKind; + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + private final ElementKind ek = null; + } + """) .doTest(); } @@ -176,14 +197,18 @@ public void enumsMayBeImmutable() { compilationHelper .addSourceLines( "Kind.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable enum Kind { A, B, C; }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable enum Kind { A, B, C; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " private final Kind k = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + private final Kind k = null; + } + """) .doTest(); } @@ -192,11 +217,13 @@ public void mutableArray() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:", - " final int[] xs = {42};", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: + final int[] xs = {42}; + } + """) .doTest(); } @@ -205,8 +232,10 @@ public void annotatedImmutableInterfaces() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface Test {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable interface Test {} + """) .doTest(); } @@ -215,14 +244,18 @@ public void immutableInterfaceField() { compilationHelper .addSourceLines( "MyInterface.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface MyInterface {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable interface MyInterface {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final MyInterface i = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final MyInterface i = null; + } + """) .doTest(); } @@ -231,11 +264,13 @@ public void deeplyImmutableArguments() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class Test {", - " final ImmutableList>> l = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class Test { + final ImmutableList>> l = null; + } + """) .doTest(); } @@ -244,11 +279,13 @@ public void mutableNonFinalField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: non-final", - " int a = 42;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: non-final + int a = 42; + } + """) .doTest(); } @@ -257,10 +294,12 @@ public void ignoreStaticFields() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " static int a = 42;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + static int a = 42; + } + """) .doTest(); } @@ -269,12 +308,14 @@ public void mutableField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.Map;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:", - " final Map a = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.Map; + @Immutable class Test { + // BUG: Diagnostic contains: + final Map a = null; + } + """) .doTest(); } @@ -283,13 +324,15 @@ public void deeplyMutableTypeArguments() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.Map;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: instantiated with mutable type for 'E'", - " final ImmutableList>>> l = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.Map; + import com.google.common.collect.ImmutableList; + @Immutable class Test { + // BUG: Diagnostic contains: instantiated with mutable type for 'E' + final ImmutableList>>> l = null; + } + """) .doTest(); } @@ -298,12 +341,14 @@ public void rawImpliesImmutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:", - " final ImmutableList l = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class Test { + // BUG: Diagnostic contains: + final ImmutableList l = null; + } + """) .doTest(); } @@ -312,28 +357,40 @@ public void extendsImmutable() { compilationHelper .addSourceLines( "Super.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable public class Super {", - " public final int x = 42;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable public class Super { + public final int x = 42; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test extends Super {", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test extends Super { + } + """) .doTest(); } @Test public void extendsMutable() { compilationHelper - .addSourceLines("Super.java", "public class Super {", " public int x = 42;", "}") + .addSourceLines( + "Super.java", + """ + public class Super { + public int x = 42; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "// BUG: Diagnostic contains: 'Super' has non-final field 'x'", - "@Immutable class Test extends Super {", - "}") + """ + import com.google.errorprone.annotations.Immutable; + // BUG: Diagnostic contains: 'Super' has non-final field 'x' + @Immutable class Test extends Super { + } + """) .doTest(); } @@ -342,17 +399,21 @@ public void extendsImmutableAnnotated_substBounds() { compilationHelper .addSourceLines( "SuperMost.java", - "import com.google.errorprone.annotations.Immutable;", - "public class SuperMost {", - " public final B x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + public class SuperMost { + public final B x = null; + } + """) .addSourceLines( "Super.java", - "import java.util.List;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf={\"A\"}) public class Super extends SuperMost {", - " public final int x = 42;", - "}") + """ + import java.util.List; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf={"A"}) public class Super extends SuperMost { + public final int x = 42; + } + """) .doTest(); } @@ -361,17 +422,21 @@ public void extendsImmutableAnnotated_mutableBounds() { compilationHelper .addSourceLines( "SuperMost.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf={\"A\"})", - "public class SuperMost {", - " public final A x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf={"A"}) + public class SuperMost { + public final A x = null; + } + """) .addSourceLines( "SubClass.java", - "import java.util.List;", - "import com.google.errorprone.annotations.Immutable;", - " // BUG: Diagnostic contains: instantiated with mutable type for 'A'", - "@Immutable public class SubClass extends SuperMost> {}") + """ + import java.util.List; + import com.google.errorprone.annotations.Immutable; + // BUG: Diagnostic contains: instantiated with mutable type for 'A' + @Immutable public class SubClass extends SuperMost> {} + """) .doTest(); } @@ -380,18 +445,20 @@ public void withinMutableClass() { compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.ArrayList;", - "import java.util.List;", - "class A {", - " List xs = new ArrayList<>();", - " // BUG: Diagnostic contains: has mutable enclosing instance", - " @Immutable class B {", - " int get() {", - " return xs.get(0);", - " }", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.ArrayList; + import java.util.List; + class A { + List xs = new ArrayList<>(); + // BUG: Diagnostic contains: has mutable enclosing instance + @Immutable class B { + int get() { + return xs.get(0); + } + } + } + """) .doTest(); } @@ -400,25 +467,26 @@ public void localClassCapturingMutableState() { compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.ArrayList;", - "import java.util.List;", - "@Immutable", - "class A {", - " @Immutable interface B { int get(); }", - " void test() {", - " List xs = new ArrayList<>();", - " @Immutable", - " // BUG: Diagnostic contains: This anonymous class implements @Immutable interface" - + " 'B', but closes over 'xs', which is not @Immutable because 'List' is mutable", - " class C implements B {", - " @Override", - " public int get() {", - " return xs.get(0);", - " }", - " }", - " }", - "}") + """ +import com.google.errorprone.annotations.Immutable; +import java.util.ArrayList; +import java.util.List; +@Immutable +class A { + @Immutable interface B { int get(); } + void test() { + List xs = new ArrayList<>(); + @Immutable + // BUG: Diagnostic contains: This anonymous class implements @Immutable interface 'B', but closes over 'xs', which is not @Immutable because 'List' is mutable + class C implements B { + @Override + public int get() { + return xs.get(0); + } + } + } +} +""") .doTest(); } @@ -427,11 +495,13 @@ public void typeParameterWithImmutableBound() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable(containerOf=\"T\") class Test> {", - " final T t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable(containerOf="T") class Test> { + final T t = null; + } + """) .doTest(); } @@ -440,16 +510,20 @@ public void immutableTypeArgumentInstantiation() { compilationHelper .addSourceLines( "Holder.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public class Holder {", - " public final T t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public class Holder { + public final T t = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final Holder h = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final Holder h = null; + } + """) .doTest(); } @@ -458,17 +532,21 @@ public void mutableTypeArgumentInstantiation() { compilationHelper .addSourceLines( "Holder.java", - "import com.google.errorprone.annotations.Immutable;", - "public class Holder {", - " public final T t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + public class Holder { + public final T t = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:", - " final Holder h = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: + final Holder h = null; + } + """) .doTest(); } @@ -477,17 +555,21 @@ public void instantiationWithMutableType() { compilationHelper .addSourceLines( "Holder.java", - "import com.google.errorprone.annotations.Immutable;", - "public class Holder {", - " public final T t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + public class Holder { + public final T t = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: not annotated", - " final Holder h = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: not annotated + final Holder h = null; + } + """) .doTest(); } @@ -496,22 +578,28 @@ public void transitiveSuperSubstitutionImmutable() { compilationHelper .addSourceLines( "SuperMostType.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"N\") public class SuperMostType {", - " public final N f = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="N") public class SuperMostType { + public final N f = null; + } + """) .addSourceLines( "MiddleClass.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"M\") public class MiddleClass extends SuperMostType {", - " // Empty", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="M") public class MiddleClass extends SuperMostType { + // Empty + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test extends MiddleClass {", - " final MiddleClass f = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test extends MiddleClass { + final MiddleClass f = null; + } + """) .doTest(); } @@ -521,25 +609,31 @@ public void containerOf_extendsImmutable() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class X {", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class X { + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - " // BUG: Diagnostic contains: 'V' is a mutable type variable", - "@Immutable(containerOf=\"V\") class Test extends X {", - " private final V t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + // BUG: Diagnostic contains: 'V' is a mutable type variable + @Immutable(containerOf="V") class Test extends X { + private final V t = null; + } + """) .addSourceLines( "MutableLeak.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class MutableLeak {", - " private static class Mutable {", - " int mutableInt;", - " }", - " private final X bad = new Test();", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class MutableLeak { + private static class Mutable { + int mutableInt; + } + private final X bad = new Test(); + } + """) .doTest(); } @@ -548,19 +642,23 @@ public void containerOf_mutableInstantiation() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"V\") class X {", - " private final V t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="V") class X { + private final V t = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:", - " // 'X' was instantiated with mutable type for 'V'", - " // 'T' is a mutable type variable", - " private final X t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: + // 'X' was instantiated with mutable type for 'V' + // 'T' is a mutable type variable + private final X t = null; + } + """) .doTest(); } @@ -569,12 +667,14 @@ public void missingContainerOf() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: 'T' is a mutable type variable", - " private final T t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + @Immutable class Test { + // BUG: Diagnostic contains: 'T' is a mutable type variable + private final T t = null; + } + """) .doTest(); } @@ -583,23 +683,29 @@ public void transitiveSuperSubstitutionMutable() { compilationHelper .addSourceLines( "SuperMostType.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"N\") public class SuperMostType {", - " public final N f = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="N") public class SuperMostType { + public final N f = null; + } + """) .addSourceLines( "MiddleClass.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"M\") public class MiddleClass extends SuperMostType {", - " // Empty", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="M") public class MiddleClass extends SuperMostType { + // Empty + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "// BUG: Diagnostic contains: instantiated with mutable type for 'M'", - "@Immutable class Test extends MiddleClass {", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + // BUG: Diagnostic contains: instantiated with mutable type for 'M' + @Immutable class Test extends MiddleClass { + } + """) .doTest(); } @@ -608,18 +714,22 @@ public void immutableInstantiation() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public class X {", - " final ImmutableList xs = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public class X { + final ImmutableList xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "@Immutable class Test {", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + @Immutable class Test { + final X x = null; + } + """) .doTest(); } @@ -628,15 +738,19 @@ public void mutableInstantiation() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "public class X { final ImmutableList xs = null; }") + """ + import com.google.common.collect.ImmutableList; + public class X { final ImmutableList xs = null; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - "// BUG: Diagnostic contains:", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: + final X x = null; + } + """) .doTest(); } @@ -645,16 +759,20 @@ public void immutableInstantiation_superBound() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "public class X { final ImmutableList xs = null; }") + """ + import com.google.common.collect.ImmutableList; + public class X { final ImmutableList xs = null; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + @Immutable class Test { + // BUG: Diagnostic contains: + final X x = null; + } + """) .doTest(); } @@ -663,16 +781,20 @@ public void mutableInstantiation_superBound() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "public class X { final ImmutableList xs = null; }") + """ + import com.google.common.collect.ImmutableList; + public class X { final ImmutableList xs = null; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: is not annotated", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + @Immutable class Test { + // BUG: Diagnostic contains: is not annotated + final X x = null; + } + """) .doTest(); } @@ -681,18 +803,22 @@ public void immutableInstantiation_extendsBound() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public class X {", - " final ImmutableList xs = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public class X { + final ImmutableList xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "@Immutable class Test {", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + @Immutable class Test { + final X x = null; + } + """) .doTest(); } @@ -701,19 +827,23 @@ public void mutableInstantiation_wildcard() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public class X {", - " // BUG: Diagnostic contains: mutable type for 'E', 'Object' is mutable", - " final ImmutableList xs = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public class X { + // BUG: Diagnostic contains: mutable type for 'E', 'Object' is mutable + final ImmutableList xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "@Immutable class Test {", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + @Immutable class Test { + final X x = null; + } + """) .doTest(); } @@ -722,19 +852,23 @@ public void mutableInstantiation_extendsBound() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable(containerOf=\"T\") public class X {", - " final ImmutableList xs = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable(containerOf="T") public class X { + final ImmutableList xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: instantiated with mutable type", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + @Immutable class Test { + // BUG: Diagnostic contains: instantiated with mutable type + final X x = null; + } + """) .doTest(); } @@ -743,11 +877,13 @@ public void containerOf_noSuchType() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "// BUG: Diagnostic contains: could not find type(s) referenced by containerOf: Z", - "@Immutable(containerOf=\"Z\") public class X {", - " final int xs = 1;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + // BUG: Diagnostic contains: could not find type(s) referenced by containerOf: Z + @Immutable(containerOf="Z") public class X { + final int xs = 1; + } + """) .doTest(); } @@ -756,37 +892,57 @@ public void immutableInstantiation_inferredImmutableType() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public class X {", - " final T xs = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public class X { + final T xs = null; + } + """) .addSourceLines( "Y.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public class Y {", - " final X xs = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public class Y { + final X xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final Y x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final Y x = null; + } + """) .doTest(); } @Test public void mutableInstantiation_inferredImmutableType() { compilationHelper - .addSourceLines("X.java", "public class X {", " final T xs = null;", "}") - .addSourceLines("Y.java", "public class Y {", " final X xs = null;", "}") + .addSourceLines( + "X.java", + """ + public class X { + final T xs = null; + } + """) + .addSourceLines( + "Y.java", + """ + public class Y { + final X xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:", - " final Y x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: + final Y x = null; + } + """) .doTest(); } @@ -795,18 +951,22 @@ public void mutableWildInstantiation() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public class X {", - " final ImmutableList xs = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public class X { + final ImmutableList xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: instantiated", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: instantiated + final X x = null; + } + """) .doTest(); } @@ -815,18 +975,22 @@ public void mutableWildcardInstantiation_immutableTypeParameter() { compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "@Immutable", - "class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.errorprone.annotations.ImmutableTypeParameter; + @Immutable + class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "B.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable", - "class B {", - " private final A a;", - " public B(A a) { this.a = a; }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable + class B { + private final A a; + public B(A a) { this.a = a; } + } + """) .doTest(); } @@ -835,18 +999,22 @@ public void mutableRawType() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public class X {", - " final ImmutableList xs = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public class X { + final ImmutableList xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: raw", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: raw + final X x = null; + } + """) .doTest(); } @@ -855,11 +1023,13 @@ public void immutableListImplementation() { compilationHelper .addSourceLines( "com/google/common/collect/ImmutableList.java", - "package com.google.common.collect;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class ImmutableList {", - " public Object[] veryMutable = null;", - "}") + """ + package com.google.common.collect; + import com.google.errorprone.annotations.Immutable; + @Immutable class ImmutableList { + public Object[] veryMutable = null; + } + """) .doTest(); } @@ -868,23 +1038,27 @@ public void positiveAnonymous() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "class Test {{", - " new Super() {", - " // BUG: Diagnostic contains: non-final", - " int x = 0;", - " {", - " x++;", - " }", - " };", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + class Test {{ + new Super() { + // BUG: Diagnostic contains: non-final + int x = 0; + { + x++; + } + }; + }} + """) .doTest(); } @@ -893,23 +1067,27 @@ public void positiveAnonymousInterface() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable interface Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "class Test {{", - " new Super() {", - " // BUG: Diagnostic contains: non-final", - " int x = 0;", - " {", - " x++;", - " }", - " };", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + class Test {{ + new Super() { + // BUG: Diagnostic contains: non-final + int x = 0; + { + x++; + } + }; + }} + """) .doTest(); } @@ -918,20 +1096,24 @@ public void negativeParametricAnonymous() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") class Super {", - " private final T t = null;", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") class Super { + private final T t = null; + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "class Test {", - " static Super get() {", - " return new Super() {};", - " }", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + class Test { + static Super get() { + return new Super() {}; + } + } + """) .doTest(); } @@ -940,16 +1122,20 @@ public void interface_containerOf_immutable() { compilationHelper .addSourceLines( "MyList.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public interface MyList {", - " T get(int i);", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public interface MyList { + T get(int i); + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "public class Test {", - " private final MyList l = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + public class Test { + private final MyList l = null; + } + """) .doTest(); } @@ -958,17 +1144,21 @@ public void interface_containerOf_mutable() { compilationHelper .addSourceLines( "MyList.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public interface MyList {", - " T get(int i);", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public interface MyList { + T get(int i); + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable public class Test {", - " // BUG: Diagnostic contains: mutable type for 'T'", - " private final MyList l = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable public class Test { + // BUG: Diagnostic contains: mutable type for 'T' + private final MyList l = null; + } + """) .doTest(); } @@ -977,17 +1167,21 @@ public void implementsInterface_containerOf() { compilationHelper .addSourceLines( "MyList.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") public interface MyList {", - " T get(int i);", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") public interface MyList { + T get(int i); + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "// BUG: Diagnostic contains: 'X' is a mutable type", - "@Immutable public class Test implements MyList {", - " public X get(int i) { return null; }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + // BUG: Diagnostic contains: 'X' is a mutable type + @Immutable public class Test implements MyList { + public X get(int i) { return null; } + } + """) .doTest(); } @@ -998,19 +1192,21 @@ public void positive() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "class Test extends Super {", - " // BUG: Diagnostic contains:" - + " Class extends @Immutable type threadsafety.Super, but is not immutable: 'Test'" - + " has non-final field 'x'", - " public int x = 0;", - "}") + """ +package threadsafety; +class Test extends Super { + // BUG: Diagnostic contains: Class extends @Immutable type threadsafety.Super, but is not immutable: 'Test' has non-final field 'x' + public int x = 0; +} +""") .doTest(); } @@ -1019,17 +1215,21 @@ public void positiveContainerOf() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf={\"T\"}) class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf={"T"}) class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "class Test extends Super {", - " // BUG: Diagnostic contains: non-final", - " public int x = 0;", - "}") + """ + package threadsafety; + class Test extends Super { + // BUG: Diagnostic contains: non-final + public int x = 0; + } + """) .doTest(); } @@ -1038,17 +1238,21 @@ public void positiveImplicitContainerOf() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf={\"T\"}) class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf={"T"}) class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "class Test extends Super {", - " // BUG: Diagnostic contains: mutable type for 'U'", - " public final Test x = null;", - "}") + """ + package threadsafety; + class Test extends Super { + // BUG: Diagnostic contains: mutable type for 'U' + public final Test x = null; + } + """) .doTest(); } @@ -1057,16 +1261,20 @@ public void negative() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test extends Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable class Test extends Super { + } + """) .doTest(); } @@ -1077,22 +1285,28 @@ public void transitive() { compilationHelper .addSourceLines( "threadsafety/I.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface I {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable interface I { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "class Test implements J {", - " // BUG: Diagnostic contains: non-final field 'x'", - " public int x = 0;", - "}") + """ + package threadsafety; + class Test implements J { + // BUG: Diagnostic contains: non-final field 'x' + public int x = 0; + } + """) .addSourceLines( - "threadsafety/J.java", // - "package threadsafety;", - "interface J extends I {", - "}") + "threadsafety/J.java", + """ + package threadsafety; + interface J extends I { + } + """) .doTest(); } @@ -1102,18 +1316,22 @@ public void negativeAnonymousMutableBound() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") class Super {", - " private final T t = null;", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") class Super { + private final T t = null; + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "class Test {{", - " new Super() {};", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + class Test {{ + new Super() {}; + }} + """) .doTest(); } @@ -1122,18 +1340,22 @@ public void immutableAnonymousTypeScope() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"X\") class Super {", - " private final X t = null;", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="X") class Super { + private final X t = null; + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") class Test {{", - " new Super() {};", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") class Test {{ + new Super() {}; + }} + """) .doTest(); } @@ -1142,21 +1364,25 @@ public void immutableClassSuperTypeScope() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"Y\") class Super {", - " @Immutable(containerOf=\"X\") class Inner1 {", - " private final X x = null;", - " private final Y y = null;", - " }", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="Y") class Super { + @Immutable(containerOf="X") class Inner1 { + private final X x = null; + private final Y y = null; + } + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"U\") class Test extends Super {", - " @Immutable class Inner2 extends Inner1 {}", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="U") class Test extends Super { + @Immutable class Inner2 extends Inner1 {} + } + """) .doTest(); } @@ -1165,18 +1391,22 @@ public void immutableClassTypeScope() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"X\") class Super {", - " private final X t = null;", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="X") class Super { + private final X t = null; + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") class Test {", - " @Immutable class Inner extends Super {}", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") class Test { + @Immutable class Inner extends Super {} + } + """) .doTest(); } @@ -1185,18 +1415,22 @@ public void negativeAnonymousBound() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\") class Super {", - " private final T t = null;", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") class Super { + private final T t = null; + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "class Test {{", - " new Super() {};", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + class Test {{ + new Super() {}; + }} + """) .doTest(); } @@ -1205,17 +1439,21 @@ public void negativeAnonymous() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "class Test {{", - " new Super() {};", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + class Test {{ + new Super() {}; + }} + """) .doTest(); } @@ -1224,24 +1462,28 @@ public void positiveEnumConstant() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface Super {", - " int f();", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable interface Super { + int f(); + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable enum Test implements Super {", - " INSTANCE {", - " // BUG: Diagnostic contains: non-final", - " public int x = 0;", - " public int f() {", - " return x++;", - " }", - " }", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable enum Test implements Super { + INSTANCE { + // BUG: Diagnostic contains: non-final + public int x = 0; + public int f() { + return x++; + } + } + } + """) .doTest(); } @@ -1250,21 +1492,25 @@ public void negativeEnumConstant() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface Super {", - " void f();", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable interface Super { + void f(); + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable enum Test implements Super {", - " INSTANCE {", - " public void f() {", - " }", - " }", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable enum Test implements Super { + INSTANCE { + public void f() { + } + } + } + """) .doTest(); } @@ -1279,10 +1525,12 @@ public void immutableNull() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final int[] xs = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final int[] xs = null; + } + """) .doTest(); } @@ -1291,11 +1539,13 @@ public void suppressOnField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " @SuppressWarnings(\"Immutable\")", - " final int[] xs = {1};", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + @SuppressWarnings("Immutable") + final int[] xs = {1}; + } + """) .doTest(); } @@ -1304,13 +1554,15 @@ public void suppressOnOneField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " @SuppressWarnings(\"Immutable\")", - " final int[] xs = {1};", - " // BUG: Diagnostic contains: arrays are mutable", - " final int[] ys = {1};", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + @SuppressWarnings("Immutable") + final int[] xs = {1}; + // BUG: Diagnostic contains: arrays are mutable + final int[] ys = {1}; + } + """) .doTest(); } @@ -1319,13 +1571,15 @@ public void twoFieldsInSource() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: arrays are mutable", - " final int[] xs = {1};", - " // BUG: Diagnostic contains: arrays are mutable", - " final int[] ys = {1};", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: arrays are mutable + final int[] xs = {1}; + // BUG: Diagnostic contains: arrays are mutable + final int[] ys = {1}; + } + """) .doTest(); } @@ -1334,25 +1588,28 @@ public void protosNotOnClasspath() { compilationHelper .addSourceLines( "com/google/errorprone/annotations/Immutable.java", - "package com.google.errorprone.annotations;", - "import static java.lang.annotation.ElementType.TYPE;", - "import static java.lang.annotation.RetentionPolicy.RUNTIME;", - "import java.lang.annotation.Retention;", - "import java.lang.annotation.Target;", - "@Target(TYPE)", - "@Retention(RUNTIME)", - "public @interface Immutable {", - " String[] containerOf() default {};", - "}") + """ + package com.google.errorprone.annotations; + import static java.lang.annotation.ElementType.TYPE; + import static java.lang.annotation.RetentionPolicy.RUNTIME; + import java.lang.annotation.Retention; + import java.lang.annotation.Target; + @Target(TYPE) + @Retention(RUNTIME) + public @interface Immutable { + String[] containerOf() default {}; + } + """) .addSourceLines("Foo.java", "class Foo {}") .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains:" - + " 'Foo' is not annotated with @com.google.errorprone.annotations.Immutable", - " final Foo f = null;", - "}") + """ +import com.google.errorprone.annotations.Immutable; +@Immutable class Test { + // BUG: Diagnostic contains: 'Foo' is not annotated with @com.google.errorprone.annotations.Immutable + final Foo f = null; +} +""") .setArgs(Arrays.asList("-cp", "NOSUCH")) .doTest(); } @@ -1363,12 +1620,14 @@ public void mutableEnum() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "enum Test {", - " ;", - " // BUG: Diagnostic contains: @Immutable class has mutable field", - " private final Object o = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + enum Test { + ; + // BUG: Diagnostic contains: @Immutable class has mutable field + private final Object o = null; + } + """) .doTest(); } @@ -1378,13 +1637,15 @@ public void mutableEnumMember() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "enum Test {", - " ONE {", - " // BUG: Diagnostic contains: @Immutable class has mutable field", - " private final Object o = null;", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + enum Test { + ONE { + // BUG: Diagnostic contains: @Immutable class has mutable field + private final Object o = null; + } + } + """) .doTest(); } @@ -1397,10 +1658,12 @@ public void mutableExtendsAnnotation() { "@interface Anno {}") .addSourceLines( "Test.java", - "abstract class Test implements Anno {", - " // BUG: Diagnostic contains: @Immutable class has mutable field", - " final Object o = null;", - "}") + """ + abstract class Test implements Anno { + // BUG: Diagnostic contains: @Immutable class has mutable field + final Object o = null; + } + """) .doTest(); } @@ -1409,16 +1672,18 @@ public void mutableEnclosing() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "public class Test {", - " int x = 0;", - " // BUG: Diagnostic contains: 'Inner' has mutable enclosing instance 'Test'", - " @Immutable public class Inner {", - " public int count() {", - " return x++;", - " }", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + public class Test { + int x = 0; + // BUG: Diagnostic contains: 'Inner' has mutable enclosing instance 'Test' + @Immutable public class Inner { + public int count() { + return x++; + } + } + } + """) .doTest(); } @@ -1447,10 +1712,12 @@ public void rawClass() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final Class clazz = Test.class;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final Class clazz = Test.class; + } + """) .doTest(); } @@ -1477,14 +1744,20 @@ public void knownImmutableFlag() { CompilationTestHelper.newInstance(ImmutableChecker.class, getClass()) .setArgs(ImmutableList.of("-XepOpt:Immutable:KnownImmutable=threadsafety.SomeImmutable")) .addSourceLines( - "threadsafety/SomeImmutable.java", "package threadsafety;", "class SomeImmutable {}") + "threadsafety/SomeImmutable.java", + """ + package threadsafety; + class SomeImmutable {} + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " public final SomeImmutable s = new SomeImmutable();", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + public final SomeImmutable s = new SomeImmutable(); + } + """) .doTest(); } @@ -1493,15 +1766,21 @@ public void knownUnsafeFlag() { CompilationTestHelper.newInstance(ImmutableChecker.class, getClass()) .setArgs(ImmutableList.of("-XepOpt:Immutable:KnownMutable=threadsafety.SomeUnsafe")) .addSourceLines( - "threadsafety/SomeUnsafe.java", "package threadsafety;", "class SomeUnsafe {}") + "threadsafety/SomeUnsafe.java", + """ + package threadsafety; + class SomeUnsafe {} + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: 'SomeUnsafe' is mutable", - " public final SomeUnsafe s = new SomeUnsafe();", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + // BUG: Diagnostic contains: 'SomeUnsafe' is mutable + public final SomeUnsafe s = new SomeUnsafe(); + } + """) .doTest(); } @@ -1510,11 +1789,13 @@ public void lazyInit() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.errorprone.annotations.concurrent.LazyInit;", - "@Immutable class Test {", - " @LazyInit int a = 42;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.errorprone.annotations.concurrent.LazyInit; + @Immutable class Test { + @LazyInit int a = 42; + } + """) .doTest(); } @@ -1523,13 +1804,15 @@ public void lazyInitMutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.errorprone.annotations.concurrent.LazyInit;", - "import java.util.List;", - "@Immutable class Test {", - " // BUG: Diagnostic contains: 'List' is mutable", - " @LazyInit List a = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.errorprone.annotations.concurrent.LazyInit; + import java.util.List; + @Immutable class Test { + // BUG: Diagnostic contains: 'List' is mutable + @LazyInit List a = null; + } + """) .doTest(); } @@ -1538,12 +1821,14 @@ public void immutableTypeParameter() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class Test<@ImmutableTypeParameter T> {", - " final T t = null;", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class Test<@ImmutableTypeParameter T> { + final T t = null; + } + """) .doTest(); } @@ -1552,18 +1837,22 @@ public void immutableTypeParameterInstantiation_immutableGenericFromContext_noVi compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class Test<@ImmutableTypeParameter T> {", - " A n() {", - " return new A<>();", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + class Test<@ImmutableTypeParameter T> { + A n() { + return new A<>(); + } + } + """) .doTest(); } @@ -1571,20 +1860,23 @@ public void immutableTypeParameterInstantiation_immutableGenericFromContext_noVi public void immutableTypeParameterInstantiation_mutableGenericFromContext_violation() { compilationHelper .addSourceLines( - "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + "A.java", + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "class Test {", - " A n() {", - " // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable" - + " type variable", - " return new A<>();", - " }", - "}") + """ +class Test { + A n() { + // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable type variable + return new A<>(); + } +} +""") .doTest(); } @@ -1594,19 +1886,22 @@ public void immutableTypeParameterInstantiation_mutableGenericFromContext_violat compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "class Test {", - " static A m() {", - " // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable" - + " type variable", - " return new A<>();", - " }", - "}") + """ +class Test { + static A m() { + // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable type variable + return new A<>(); + } +} +""") .doTest(); } @@ -1615,18 +1910,22 @@ public void immutableTypeParameterInstantiation_staticMethod_genericParamAnnotat compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class Test {", - " static <@ImmutableTypeParameter T> A l() {", - " return new A<>();", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + class Test { + static <@ImmutableTypeParameter T> A l() { + return new A<>(); + } + } + """) .doTest(); } @@ -1635,19 +1934,22 @@ public void immutableTypeParameterInstantiation_genericParamNotAnnotated_violati compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "class Test {", - " A k() {", - " // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable" - + " type variable", - " return new A<>();", - " }", - "}") + """ +class Test { + A k() { + // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable type variable + return new A<>(); + } +} +""") .doTest(); } @@ -1656,18 +1958,22 @@ public void immutableTypeParameterInstantiation_genericParamAnnotated_noViolatio compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class Test {", - " <@ImmutableTypeParameter T> A k() {", - " return new A<>();", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + class Test { + <@ImmutableTypeParameter T> A k() { + return new A<>(); + } + } + """) .doTest(); } @@ -1676,23 +1982,28 @@ public void immutableTypeParameterInstantiation_genericParamExtendsMutable_viola compilationHelper .addSourceLines( "MyMutableType.java", - "import com.google.errorprone.annotations.Immutable;", - "class MyMutableType {}") + """ + import com.google.errorprone.annotations.Immutable; + class MyMutableType {} + """) .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "class Test {", - " A i() {", - " // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable" - + " type variable", - " return new A<>();", - " }", - "}") + """ +class Test { + A i() { + // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable type variable + return new A<>(); + } +} +""") .doTest(); } @@ -1701,21 +2012,27 @@ public void immutableTypeParameterInstantiation_genericParamExtendsImmutable_noV compilationHelper .addSourceLines( "MyImmutableType.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class MyImmutableType {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class MyImmutableType {} + """) .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "class Test {", - " A h() {", - " return new A<>();", - " }", - "}") + """ + class Test { + A h() { + return new A<>(); + } + } + """) .doTest(); } @@ -1724,18 +2041,22 @@ public void immutableTypeParameterInstantiation_violation() { compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( "Test.java", - "class Test {", - " A g() {", - " // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'Object' is mutable", - " return new A<>();", - " }", - "}") + """ + class Test { + A g() { + // BUG: Diagnostic contains: instantiation of 'T' is mutable, 'Object' is mutable + return new A<>(); + } + } + """) .doTest(); } @@ -1744,12 +2065,21 @@ public void immutableTypeParameterInstantiation_noViolation() { compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class A<@ImmutableTypeParameter T> {} + """) .addSourceLines( - "Test.java", "class Test {", " A f() {", " return new A<>();", " }", "}") + "Test.java", + """ + class Test { + A f() { + return new A<>(); + } + } + """) .doTest(); } @@ -1758,10 +2088,12 @@ public void immutableTypeParameterUsage() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class T {", - " static <@ImmutableTypeParameter T> void f() {}", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + class T { + static <@ImmutableTypeParameter T> void f() {} + } + """) .doTest(); } @@ -1770,10 +2102,12 @@ public void immutableTypeParameterUsage_interface() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "@Immutable interface T<@ImmutableTypeParameter T> {", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import com.google.errorprone.annotations.ImmutableTypeParameter; + @Immutable interface T<@ImmutableTypeParameter T> { + } + """) .doTest(); } @@ -1782,8 +2116,10 @@ public void immutableTypeParameterMutableClass() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class A<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + class A<@ImmutableTypeParameter T> {} + """) .doTest(); } @@ -1792,20 +2128,22 @@ public void immutableTypeParameter_notAllTypeVarsInstantiated() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.function.Function;", - "class Test {", - " public final void f1(A transform) {}", - " public C f2(Function fn) {", - " return null;", - " }", - " public final void f3(Function fn) {", - " // BUG: Diagnostic contains: instantiation of 'C' is mutable", - " // 'E' is a mutable type variable", - " f1(f2(fn));", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import java.util.function.Function; + class Test { + public final void f1(A transform) {} + public C f2(Function fn) { + return null; + } + public final void f3(Function fn) { + // BUG: Diagnostic contains: instantiation of 'C' is mutable + // 'E' is a mutable type variable + f1(f2(fn)); + } + } + """) .doTest(); } @@ -1817,20 +2155,22 @@ public void immutableTypeParameter_notAllTypeVarsInstantiated_shouldFail() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.function.Function;", - "class Test {", - " public final void f1(A transform) {}", - " public <@ImmutableTypeParameter B, C> C f2(Function fn) {", - " return null;", - " }", - " public final void f3(Function fn) {", - " // BUG: Diagnostic contains: instantiation of 'B' is mutable", - " // 'D' is a mutable type variable", - " f1(f2(fn));", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import java.util.function.Function; + class Test { + public final void f1(A transform) {} + public <@ImmutableTypeParameter B, C> C f2(Function fn) { + return null; + } + public final void f3(Function fn) { + // BUG: Diagnostic contains: instantiation of 'B' is mutable + // 'D' is a mutable type variable + f1(f2(fn)); + } + } + """) .doTest(); } @@ -1839,15 +2179,19 @@ public void containerOf_extendsThreadSafe() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class X {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class X {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "// BUG: Diagnostic contains: 'X' is not a container of 'V'", - "@Immutable(containerOf = {\"Y\"}) class Test extends X {", - " private final Y t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + // BUG: Diagnostic contains: 'X' is not a container of 'V' + @Immutable(containerOf = {"Y"}) class Test extends X { + private final Y t = null; + } + """) .doTest(); } @@ -1856,14 +2200,18 @@ public void containerOf_extendsThreadSafeContainerOf() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf = {\"V\"}) class X {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf = {"V"}) class X {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf = {\"Y\"}) class Test extends X {", - " private final Y t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf = {"Y"}) class Test extends X { + private final Y t = null; + } + """) .doTest(); } @@ -1872,14 +2220,18 @@ public void containerOf_extendsThreadSafe_nonContainer() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf = {\"V\"}) class X {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf = {"V"}) class X {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf = {\"Y\"}) class Test extends X {", - " private final Y t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf = {"Y"}) class Test extends X { + private final Y t = null; + } + """) .doTest(); } @@ -1888,15 +2240,19 @@ public void containerOf_extendsThreadSafe_interface() { compilationHelper .addSourceLines( "X.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface X {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable interface X {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "// BUG: Diagnostic contains: 'X' is not a container of 'V'", - "@Immutable(containerOf = {\"Y\"}) class Test implements X {", - " private final Y t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + // BUG: Diagnostic contains: 'X' is not a container of 'V' + @Immutable(containerOf = {"Y"}) class Test implements X { + private final Y t = null; + } + """) .doTest(); } @@ -1904,15 +2260,19 @@ public void containerOf_extendsThreadSafe_interface() { public void containerOf_field() { compilationHelper .addSourceLines( - "X.java", // - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface X {}") + "X.java", + """ + import com.google.errorprone.annotations.Immutable; + @Immutable interface X {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"V\") class Test {", - " private final X t = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="V") class Test { + private final X t = null; + } + """) .doTest(); } @@ -1921,12 +2281,14 @@ public void annotatedClassType() { compilationHelper .addSourceLines( "Test.java", - "import static java.lang.annotation.ElementType.TYPE_USE;", - "import java.lang.annotation.Target;", - "@Target(TYPE_USE) @interface A {}", - "class Test {", - " Object o = new @A Object();", - "}") + """ + import static java.lang.annotation.ElementType.TYPE_USE; + import java.lang.annotation.Target; + @Target(TYPE_USE) @interface A {} + class Test { + Object o = new @A Object(); + } + """) .doTest(); } @@ -1936,19 +2298,21 @@ public void immutableInterfaceImplementationCapturesMutableState() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface I {", - " int f();", - "}", - "class Test {", - " int x;", - " I one = new I() {", - " public int f() {", - " return x++;", - " }", - " };", - " I two = () -> x++;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable interface I { + int f(); + } + class Test { + int x; + I one = new I() { + public int f() { + return x++; + } + }; + I two = () -> x++; + } + """) .doTest(); } @@ -1957,17 +2321,21 @@ public void immutableUpperBound() { compilationHelper .addSourceLines( "MyImmutableType.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class MyImmutableType {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class MyImmutableType {} + """) .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final T t = null;", - " final U u = null;", - " final ImmutableList v = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final T t = null; + final U u = null; + final ImmutableList v = null; + } + """) .doTest(); } @@ -1976,11 +2344,13 @@ public void immutableRecursiveUpperBound() { compilationHelper .addSourceLines( "Recursive.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable", - "abstract class Recursive> {", - " final T x = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable + abstract class Recursive> { + final T x = null; + } + """) .doTest(); } @@ -1989,14 +2359,16 @@ public void immutableRecursiveUpperBound_notImmutable() { compilationHelper .addSourceLines( "Recursive.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "@Immutable", - "abstract class Recursive> {", - " final T x = null;", - " // BUG: Diagnostic contains: 'Recursive' has field 'y' of type 'java.util.List'", - " final List y = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + @Immutable + abstract class Recursive> { + final T x = null; + // BUG: Diagnostic contains: 'Recursive' has field 'y' of type 'java.util.List' + final List y = null; + } + """) .doTest(); } @@ -2005,34 +2377,44 @@ public void immutableUpperBoundAndContainerOfInconsistency() { compilationHelper .addSourceLines( "ImmutableInterface.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface ImmutableInterface {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable interface ImmutableInterface {} + """) .addSourceLines( "MutableImpl.java", - "import com.google.errorprone.annotations.Immutable;", - "@SuppressWarnings(\"Immutable\") class MutableImpl implements ImmutableInterface {", - " int mutableField;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @SuppressWarnings("Immutable") class MutableImpl implements ImmutableInterface { + int mutableField; + } + """) .addSourceLines( "WithContainerOf.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf=\"T\")", - "class WithContainerOf { final T x = null; }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf="T") + class WithContainerOf { final T x = null; } + """) .addSourceLines( "WithoutContainerOf.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable", - "class WithoutContainerOf { final T x = null; }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable + class WithoutContainerOf { final T x = null; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final WithContainerOf a = null;", - " final WithoutContainerOf b = null;", - " // BUG: Diagnostic contains: field 'c' of type 'WithContainerOf'", - " final WithContainerOf c = null;", - " final WithoutContainerOf d = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final WithContainerOf a = null; + final WithoutContainerOf b = null; + // BUG: Diagnostic contains: field 'c' of type 'WithContainerOf' + final WithContainerOf c = null; + final WithoutContainerOf d = null; + } + """) .doTest(); } @@ -2042,17 +2424,19 @@ public void immutableTypeParameter_twoInstantiations() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "import com.google.common.collect.ImmutableList;", - "@Immutable class Test<@ImmutableTypeParameter T> {", - " <@ImmutableTypeParameter T> T f(T t) { return t; }", - " <@ImmutableTypeParameter T> void g(T a, T b) {}", - " @Immutable interface I {}", - " void test(I i) {", - " g(f(i), f(i));", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + import com.google.common.collect.ImmutableList; + @Immutable class Test<@ImmutableTypeParameter T> { + <@ImmutableTypeParameter T> T f(T t) { return t; } + <@ImmutableTypeParameter T> void g(T a, T b) {} + @Immutable interface I {} + void test(I i) { + g(f(i), f(i)); + } + } + """) .doTest(); } @@ -2062,22 +2446,24 @@ public void immutableTypeParameter_instantiations_negative() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "abstract class T {", - " interface S {}", - " interface L {}", - " interface A {}", - " @Immutable interface B extends A {}", - " @Immutable interface C extends B {}", - " abstract void h(S firstType, S secondType, S thirdType);", - " abstract <@ImmutableTypeParameter E extends A> S f(Class entityClass);", - " abstract S> g(S element);", - " void test() {", - " // BUG: Diagnostic contains: the declaration of type 'T.A' is not annotated", - " h(f(A.class), g(f(B.class)), g(f(C.class)));", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + abstract class T { + interface S {} + interface L {} + interface A {} + @Immutable interface B extends A {} + @Immutable interface C extends B {} + abstract void h(S firstType, S secondType, S thirdType); + abstract <@ImmutableTypeParameter E extends A> S f(Class entityClass); + abstract S> g(S element); + void test() { + // BUG: Diagnostic contains: the declaration of type 'T.A' is not annotated + h(f(A.class), g(f(B.class)), g(f(C.class))); + } + } + """) .doTest(); } @@ -2087,16 +2473,19 @@ public void immutableTypeParameter_rawSuper() { compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class S<@ImmutableTypeParameter X> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import com.google.errorprone.annotations.Immutable; + @Immutable class S<@ImmutableTypeParameter X> {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import com.google.errorprone.annotations.Immutable;", - "// BUG: Diagnostic contains: 'S' required instantiation of 'X' with type parameters," - + " but was raw", - "@Immutable class T<@ImmutableTypeParameter X> extends S {}") + """ +import com.google.errorprone.annotations.ImmutableTypeParameter; +import com.google.errorprone.annotations.Immutable; +// BUG: Diagnostic contains: 'S' required instantiation of 'X' with type parameters, but was raw +@Immutable class T<@ImmutableTypeParameter X> extends S {} +""") .doTest(); } @@ -2117,8 +2506,10 @@ public void containerOf_noViolation() { withImmutableTypeParameterGeneric() .addSourceLines( "ImmutableContainer.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf = \"T\") class ImmutableContainer { }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf = "T") class ImmutableContainer { } + """) .addSourceLines( "Test.class", "class Test {", @@ -2280,8 +2671,10 @@ public void typeParameterExtendsImmutable_noViolation() { withImmutableTypeParameterGeneric() .addSourceLines( "ImmutableClass.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class ImmutableClass { }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class ImmutableClass { } + """) .addSourceLines( "Test.class", "class Test {", @@ -2297,8 +2690,10 @@ public void typeParameterSuper_noViolation() { withImmutableTypeParameterGeneric() .addSourceLines( "ImmutableClass.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class ImmutableClass { }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class ImmutableClass { } + """) .addSourceLines( "Test.class", "class Test {", @@ -2314,8 +2709,10 @@ public void extendsImmutable_noViolation() { withImmutableTypeParameterGeneric() .addSourceLines( "ImmutableClass.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class ImmutableClass { }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class ImmutableClass { } + """) .addSourceLines( "ChildGenericWithImmutableParam.java", "class ChildGenericWithImmutableParam extends" @@ -2329,20 +2726,22 @@ public void methodInvocation_violation() { .addSourceLines("MutableClass.java", "class MutableClass { }") .addSourceLines( "Clazz.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class Clazz {", - " public <@ImmutableTypeParameter T> void method(int m, T v) { }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + class Clazz { + public <@ImmutableTypeParameter T> void method(int m, T v) { } + } + """) .addSourceLines( "Invoker.java", - "class Invoker {", - " public void method() {", - " // BUG: Diagnostic contains: instantiation of 'T' is mutable, the declaration of" - + " type 'MutableClass' is not annotated with" - + " @com.google.errorprone.annotations.Immutable", - " new Clazz().method(78, new MutableClass());", - " }", - "}") + """ +class Invoker { + public void method() { + // BUG: Diagnostic contains: instantiation of 'T' is mutable, the declaration of type 'MutableClass' is not annotated with @com.google.errorprone.annotations.Immutable + new Clazz().method(78, new MutableClass()); + } +} +""") .doTest(); } @@ -2351,8 +2750,10 @@ public void containerOfAsImmutableTypeParameter_noViolation() { withImmutableTypeParameterGeneric() .addSourceLines( "Container.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf = {\"T\"}) class Container {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf = {"T"}) class Container {} + """) .addSourceLines( "Clazz.java", "class Clazz { private GenericWithImmutableParam> container; }") @@ -2364,10 +2765,12 @@ public void containerOfAsImmutableTypeParameterInSameClass_noViolation() { withImmutableTypeParameterGeneric() .addSourceLines( "Container.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable(containerOf = {\"T\"}) class Container { ", - " GenericWithImmutableParam method() { return null; }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable(containerOf = {"T"}) class Container { + GenericWithImmutableParam method() { return null; } + } + """) .doTest(); } @@ -2376,9 +2779,11 @@ public void immutableTypeParameter_recursiveUpperBound() { compilationHelper .addSourceLines( "B.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable", - "abstract class B> {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable + abstract class B> {} + """) .doTest(); } @@ -2387,13 +2792,17 @@ public void immutableTypeParameter_recursiveUpperBoundUsage() { compilationHelper .addSourceLines( "B.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable", - "interface B> {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable + interface B> {} + """) .addSourceLines( "A.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class A implements B { final B value = null; }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class A implements B { final B value = null; } + """) .doTest(); } @@ -2413,11 +2822,12 @@ public void immutableTypeParameter_anonymousInstantiation_noViolation() { withImmutableTypeParameterGeneric() .addSourceLines( "Clazz.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class Clazz {", - " private static final GenericWithImmutableParam value = new" - + " GenericWithImmutableParam() {};", - "}") + """ +import com.google.errorprone.annotations.ImmutableTypeParameter; +class Clazz { + private static final GenericWithImmutableParam value = new GenericWithImmutableParam() {}; +} +""") .doTest(); } @@ -2426,15 +2836,14 @@ public void immutableTypeParameter_anonymousInstantiation_violation() { withImmutableTypeParameterGeneric() .addSourceLines( "Clazz.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class Clazz {", - " // BUG: Diagnostic contains: instantiation of 'T' is mutable, the declaration of" - + " type 'Clazz.MutableClass' is not annotated with" - + " @com.google.errorprone.annotations.Immutable", - " private static final GenericWithImmutableParam value = new" - + " GenericWithImmutableParam() {};", - " private static class MutableClass {}", - "}") + """ +import com.google.errorprone.annotations.ImmutableTypeParameter; +class Clazz { + // BUG: Diagnostic contains: instantiation of 'T' is mutable, the declaration of type 'Clazz.MutableClass' is not annotated with @com.google.errorprone.annotations.Immutable + private static final GenericWithImmutableParam value = new GenericWithImmutableParam() {}; + private static class MutableClass {} +} +""") .doTest(); } @@ -2453,11 +2862,10 @@ public void nonGeneric_inheritanceClass_violation() { .addSourceLines("MutableClass.java", "class MutableClass {}") .addSourceLines( "ChildGenericWithImmutableParam.java", - "// BUG: Diagnostic contains: instantiation of 'T' is mutable, the declaration of type" - + " 'MutableClass' is not annotated with" - + " @com.google.errorprone.annotations.Immutable", - "class ChildGenericWithImmutableParam extends GenericWithImmutableParam {" - + " }") + """ +// BUG: Diagnostic contains: instantiation of 'T' is mutable, the declaration of type 'MutableClass' is not annotated with @com.google.errorprone.annotations.Immutable +class ChildGenericWithImmutableParam extends GenericWithImmutableParam { } +""") .doTest(); } @@ -2466,8 +2874,10 @@ public void nonGeneric_inheritanceInterface_noViolation() { compilationHelper .addSourceLines( "GenericWithImmutableParamIface.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "interface GenericWithImmutableParamIface<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + interface GenericWithImmutableParamIface<@ImmutableTypeParameter T> {} + """) .addSourceLines( "ChildGenericWithImmutableParam.java", "class ChildGenericWithImmutableParam implements GenericWithImmutableParamIface" @@ -2480,16 +2890,17 @@ public void nonGeneric_inheritanceInterface_violation() { compilationHelper .addSourceLines( "GenericWithImmutableParamIface.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "interface GenericWithImmutableParamIface<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + interface GenericWithImmutableParamIface<@ImmutableTypeParameter T> {} + """) .addSourceLines("MutableClass.java", "class MutableClass {}") .addSourceLines( "ChildGenericWithImmutableParam.java", - "// BUG: Diagnostic contains: instantiation of 'T' is mutable, the declaration of type" - + " 'MutableClass' is not annotated with" - + " @com.google.errorprone.annotations.Immutable", - "class ChildGenericWithImmutableParam implements" - + " GenericWithImmutableParamIface { }") + """ +// BUG: Diagnostic contains: instantiation of 'T' is mutable, the declaration of type 'MutableClass' is not annotated with @com.google.errorprone.annotations.Immutable +class ChildGenericWithImmutableParam implements GenericWithImmutableParamIface { } +""") .doTest(); } @@ -2498,9 +2909,10 @@ public void inheritanceClass_violation() { withImmutableTypeParameterGeneric() .addSourceLines( "ChildGenericWithImmutableParam.java", - "// BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable type" - + " variable", - "class ChildGenericWithImmutableParam extends GenericWithImmutableParam { }") + """ +// BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable type variable +class ChildGenericWithImmutableParam extends GenericWithImmutableParam { } +""") .doTest(); } @@ -2509,9 +2921,10 @@ public void inheritanceClass_noViolation() { withImmutableTypeParameterGeneric() .addSourceLines( "ChildGenericWithImmutableParam.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class ChildGenericWithImmutableParam<@ImmutableTypeParameter T> extends" - + " GenericWithImmutableParam { }") + """ +import com.google.errorprone.annotations.ImmutableTypeParameter; +class ChildGenericWithImmutableParam<@ImmutableTypeParameter T> extends GenericWithImmutableParam { } +""") .doTest(); } @@ -2520,14 +2933,16 @@ public void inheritanceInterface_violation() { compilationHelper .addSourceLines( "GenericWithImmutableParamIface.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "interface GenericWithImmutableParamIface<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + interface GenericWithImmutableParamIface<@ImmutableTypeParameter T> {} + """) .addSourceLines( "ChildGenericWithImmutableParam.java", - "// BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable type" - + " variable", - "class ChildGenericWithImmutableParam implements GenericWithImmutableParamIface {" - + " }") + """ +// BUG: Diagnostic contains: instantiation of 'T' is mutable, 'T' is a mutable type variable +class ChildGenericWithImmutableParam implements GenericWithImmutableParamIface { } +""") .doTest(); } @@ -2536,13 +2951,16 @@ public void inheritanceInterface_noViolation() { compilationHelper .addSourceLines( "GenericWithImmutableParamIface.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "interface GenericWithImmutableParamIface<@ImmutableTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + interface GenericWithImmutableParamIface<@ImmutableTypeParameter T> {} + """) .addSourceLines( "ChildGenericWithImmutableParam.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class ChildGenericWithImmutableParam<@ImmutableTypeParameter T> implements" - + " GenericWithImmutableParamIface { }") + """ +import com.google.errorprone.annotations.ImmutableTypeParameter; +class ChildGenericWithImmutableParam<@ImmutableTypeParameter T> implements GenericWithImmutableParamIface { } +""") .doTest(); } @@ -2550,8 +2968,10 @@ public void inheritanceInterface_noViolation() { private CompilationTestHelper withImmutableTypeParameterGeneric() { return compilationHelper.addSourceLines( "GenericWithImmutableParam.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "class GenericWithImmutableParam<@ImmutableTypeParameter T> {}"); + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + class GenericWithImmutableParam<@ImmutableTypeParameter T> {} + """); } @Test @@ -2559,17 +2979,19 @@ public void lambda_cannotCloseAroundMutableField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.ArrayList;", - "import java.util.List;", - "class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " private int a = 0;", - " void test(ImmutableFunction f) {", - " // BUG: Diagnostic contains:", - " test(x -> ++a);", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.ArrayList; + import java.util.List; + class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + private int a = 0; + void test(ImmutableFunction f) { + // BUG: Diagnostic contains: + test(x -> ++a); + } + } + """) .doTest(); } @@ -2578,17 +3000,19 @@ public void lambda_canCloseAroundImmutableField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.ArrayList;", - "import java.util.List;", - "class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " private final int b = 1;", - " void test(ImmutableFunction f) {", - " test(x -> b);", - " test(x -> this.b);", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.ArrayList; + import java.util.List; + class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + private final int b = 1; + void test(ImmutableFunction f) { + test(x -> b); + test(x -> this.b); + } + } + """) .doTest(); } @@ -2597,17 +3021,19 @@ public void lambda_cannotCloseAroundMutableFieldQualifiedWithThis() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.ArrayList;", - "import java.util.List;", - "class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " private int b = 1;", - " void test(ImmutableFunction f) {", - " // BUG: Diagnostic contains:", - " test(x -> this.b);", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.ArrayList; + import java.util.List; + class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + private int b = 1; + void test(ImmutableFunction f) { + // BUG: Diagnostic contains: + test(x -> this.b); + } + } + """) .doTest(); } @@ -2616,17 +3042,19 @@ public void lambda_cannotCloseAroundMutableLocal() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "import java.util.ArrayList;", - "class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " void test(ImmutableFunction f) {", - " List xs = new ArrayList<>();", - " // BUG: Diagnostic contains:", - " test(x -> xs.get(x));", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + import java.util.ArrayList; + class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + void test(ImmutableFunction f) { + List xs = new ArrayList<>(); + // BUG: Diagnostic contains: + test(x -> xs.get(x)); + } + } + """) .doTest(); } @@ -2635,15 +3063,17 @@ public void notImmutableAnnotatedLambda_noFinding() { compilationHelper .addSourceLines( "Test.java", - "import java.util.ArrayList;", - "import java.util.List;", - "import java.util.function.Function;", - "class Test {", - " void test(Function f) {", - " List xs = new ArrayList<>();", - " test(x -> xs.get(x));", - " }", - "}") + """ + import java.util.ArrayList; + import java.util.List; + import java.util.function.Function; + class Test { + void test(Function f) { + List xs = new ArrayList<>(); + test(x -> xs.get(x)); + } + } + """) .doTest(); } @@ -2652,15 +3082,17 @@ public void lambda_canHaveMutableVariablesWithin() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.ArrayList;", - "import java.util.List;", - "class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " void test(ImmutableFunction f) {", - " test(x -> { List xs = new ArrayList<>(); return xs.get(x); });", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.ArrayList; + import java.util.List; + class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + void test(ImmutableFunction f) { + test(x -> { List xs = new ArrayList<>(); return xs.get(x); }); + } + } + """) .doTest(); } @@ -2669,16 +3101,18 @@ public void lambda_canAccessStaticField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " static class A {", - " public static int FOO = 1;", - " }", - " void test(ImmutableFunction f) {", - " test(x -> A.FOO);", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + static class A { + public static int FOO = 1; + } + void test(ImmutableFunction f) { + test(x -> A.FOO); + } + } + """) .doTest(); } @@ -2687,22 +3121,19 @@ public void lambda_cannotCallMethodOnMutableClass() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "abstract class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " abstract int mutable(int a);", - " void test(ImmutableFunction f) {", - " // BUG: Diagnostic contains: This lambda implements @Immutable interface" - + " 'ImmutableFunction', but accesses instance method(s) 'mutable' on 'Test' which" - + " is not @Immutable", - " test(x -> mutable(x));", - " // BUG: Diagnostic contains: This lambda implements @Immutable interface" - + " 'ImmutableFunction', but closes over 'this', which is not @Immutable because" - + " 'Test' has field 'this' of type 'Test', the declaration of type 'Test' is not" - + " annotated with @com.google.errorprone.annotations.Immutable", - " test(x -> this.mutable(x));", - " }", - "}") + """ +import com.google.errorprone.annotations.Immutable; +abstract class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + abstract int mutable(int a); + void test(ImmutableFunction f) { + // BUG: Diagnostic contains: This lambda implements @Immutable interface 'ImmutableFunction', but accesses instance method(s) 'mutable' on 'Test' which is not @Immutable + test(x -> mutable(x)); + // BUG: Diagnostic contains: This lambda implements @Immutable interface 'ImmutableFunction', but closes over 'this', which is not @Immutable because 'Test' has field 'this' of type 'Test', the declaration of type 'Test' is not annotated with @com.google.errorprone.annotations.Immutable + test(x -> this.mutable(x)); + } +} +""") .doTest(); } @@ -2711,16 +3142,18 @@ public void lambda_canCallMethodOnImmutableClass() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable", - "abstract class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " abstract int mutable(int a);", - " void test(ImmutableFunction f) {", - " test(x -> mutable(x));", - " test(x -> this.mutable(x));", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable + abstract class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + abstract int mutable(int a); + void test(ImmutableFunction f) { + test(x -> mutable(x)); + test(x -> this.mutable(x)); + } + } + """) .doTest(); } @@ -2729,16 +3162,18 @@ public void checksEffectiveTypeOfReceiver() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.function.Function;", - "@Immutable", - "abstract class Test {", - " @Immutable interface ImmutableFunction extends Function {", - " default ImmutableFunction andThen(ImmutableFunction fn) {", - " return x -> fn.apply(apply(x));", - " }", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.function.Function; + @Immutable + abstract class Test { + @Immutable interface ImmutableFunction extends Function { + default ImmutableFunction andThen(ImmutableFunction fn) { + return x -> fn.apply(apply(x)); + } + } + } + """) .doTest(); } @@ -2747,17 +3182,19 @@ public void checksEffectiveTypeOfReceiver_whenNotDirectOuterClass() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.function.Function;", - "@Immutable", - "abstract class Test implements Function {", - " @Immutable interface ImmutableFunction { String apply(String a); }", - " class A {", - " ImmutableFunction asImmutable() {", - " return x -> apply(x);", - " }", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.function.Function; + @Immutable + abstract class Test implements Function { + @Immutable interface ImmutableFunction { String apply(String a); } + class A { + ImmutableFunction asImmutable() { + return x -> apply(x); + } + } + } + """) .doTest(); } @@ -2766,15 +3203,17 @@ public void methodReference_onImmutableType() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableMap;", - "import com.google.errorprone.annotations.Immutable;", - "abstract class Test {", - " @Immutable interface ImmutableFunction { String apply(String b); }", - " void test(ImmutableFunction f) {", - " ImmutableMap map = ImmutableMap.of();", - " test(map::get);", - " }", - "}") + """ + import com.google.common.collect.ImmutableMap; + import com.google.errorprone.annotations.Immutable; + abstract class Test { + @Immutable interface ImmutableFunction { String apply(String b); } + void test(ImmutableFunction f) { + ImmutableMap map = ImmutableMap.of(); + test(map::get); + } + } + """) .doTest(); } @@ -2783,17 +3222,19 @@ public void methodReference_onMutableType() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.HashMap;", - "import java.util.Map;", - "abstract class Test {", - " @Immutable interface ImmutableFunction { String apply(String b); }", - " void test(ImmutableFunction f) {", - " Map map = new HashMap<>();", - " // BUG: Diagnostic contains:", - " test(map::get);", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.HashMap; + import java.util.Map; + abstract class Test { + @Immutable interface ImmutableFunction { String apply(String b); } + void test(ImmutableFunction f) { + Map map = new HashMap<>(); + // BUG: Diagnostic contains: + test(map::get); + } + } + """) .doTest(); } @@ -2802,15 +3243,17 @@ public void methodReference_onExpressionWithMutableType() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.Maps;", - "import com.google.errorprone.annotations.Immutable;", - "abstract class Test {", - " @Immutable interface ImmutableFunction { String apply(String b); }", - " void test(ImmutableFunction f) {", - " // BUG: Diagnostic contains:", - " test(Maps.newHashMap()::get);", - " }", - "}") + """ + import com.google.common.collect.Maps; + import com.google.errorprone.annotations.Immutable; + abstract class Test { + @Immutable interface ImmutableFunction { String apply(String b); } + void test(ImmutableFunction f) { + // BUG: Diagnostic contains: + test(Maps.newHashMap()::get); + } + } + """) .doTest(); } @@ -2819,14 +3262,16 @@ public void methodReference_toStaticMethod() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.Lists;", - "import com.google.errorprone.annotations.Immutable;", - "abstract class Test {", - " @Immutable interface ImmutableProvider { Object get(); }", - " void test(ImmutableProvider f) {", - " test(Lists::newArrayList);", - " }", - "}") + """ + import com.google.common.collect.Lists; + import com.google.errorprone.annotations.Immutable; + abstract class Test { + @Immutable interface ImmutableProvider { Object get(); } + void test(ImmutableProvider f) { + test(Lists::newArrayList); + } + } + """) .doTest(); } @@ -2835,14 +3280,16 @@ public void methodReference_toUnboundMethodReference() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.Set;", - "abstract class Test {", - " @Immutable interface ImmutableBiConsumer { void accept(Set xs, String x); }", - " void test(ImmutableBiConsumer c) {", - " test(Set::add);", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.Set; + abstract class Test { + @Immutable interface ImmutableBiConsumer { void accept(Set xs, String x); } + void test(ImmutableBiConsumer c) { + test(Set::add); + } + } + """) .doTest(); } @@ -2851,14 +3298,16 @@ public void methodReference_toConstructor() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.ArrayList;", - "abstract class Test {", - " @Immutable interface ImmutableProvider { Object get(); }", - " void test(ImmutableProvider f) {", - " test(ArrayList::new);", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.ArrayList; + abstract class Test { + @Immutable interface ImmutableProvider { Object get(); } + void test(ImmutableProvider f) { + test(ArrayList::new); + } + } + """) .doTest(); } @@ -2867,15 +3316,17 @@ public void methodReference_immutableTypeParam() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import java.util.ArrayList;", - "abstract class Test {", - " interface ImmutableProvider<@ImmutableTypeParameter T> { T get(); }", - " void test(ImmutableProvider f) {", - " // BUG: Diagnostic contains:", - " test(ArrayList::new);", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import java.util.ArrayList; + abstract class Test { + interface ImmutableProvider<@ImmutableTypeParameter T> { T get(); } + void test(ImmutableProvider f) { + // BUG: Diagnostic contains: + test(ArrayList::new); + } + } + """) .doTest(); } @@ -2884,15 +3335,17 @@ public void lambda_immutableTypeParam() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ImmutableTypeParameter;", - "import java.util.ArrayList;", - "abstract class Test {", - " interface ImmutableProvider<@ImmutableTypeParameter T> { T get(); }", - " void test(ImmutableProvider f) {", - " // BUG: Diagnostic contains:", - " test(() -> new ArrayList<>());", - " }", - "}") + """ + import com.google.errorprone.annotations.ImmutableTypeParameter; + import java.util.ArrayList; + abstract class Test { + interface ImmutableProvider<@ImmutableTypeParameter T> { T get(); } + void test(ImmutableProvider f) { + // BUG: Diagnostic contains: + test(() -> new ArrayList<>()); + } + } + """) .doTest(); } @@ -2901,23 +3354,25 @@ public void chainedGettersAreAcceptable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.ArrayList;", - "import java.util.List;", - "class Test {", - " final Test t = null;", - " final List xs = new ArrayList<>();", - " final List getXs() {", - " return xs;", - " }", - " @Immutable interface ImmutableFunction { String apply(String b); }", - " void test(ImmutableFunction f) {", - " test(x -> {", - " Test t = new Test();", - " return t.xs.get(0) + t.getXs().get(0) + t.t.t.xs.get(0);", - " });", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.ArrayList; + import java.util.List; + class Test { + final Test t = null; + final List xs = new ArrayList<>(); + final List getXs() { + return xs; + } + @Immutable interface ImmutableFunction { String apply(String b); } + void test(ImmutableFunction f) { + test(x -> { + Test t = new Test(); + return t.xs.get(0) + t.getXs().get(0) + t.t.t.xs.get(0); + }); + } + } + """) .doTest(); } @@ -2926,21 +3381,23 @@ public void anonymousClass_cannotCloseAroundMutableLocal() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "import java.util.ArrayList;", - "class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " void test(ImmutableFunction f) {", - " List xs = new ArrayList<>();", - " // BUG: Diagnostic contains:", - " test(new ImmutableFunction<>() {", - " @Override public Integer apply(Integer x) {", - " return xs.get(x);", - " }", - " });", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + import java.util.ArrayList; + class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + void test(ImmutableFunction f) { + List xs = new ArrayList<>(); + // BUG: Diagnostic contains: + test(new ImmutableFunction<>() { + @Override public Integer apply(Integer x) { + return xs.get(x); + } + }); + } + } + """) .doTest(); } @@ -2949,21 +3406,23 @@ public void anonymousClass_hasMutableFieldSuppressed_noWarningAtUsageSite() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "import java.util.ArrayList;", - "class Test {", - " @Immutable interface ImmutableFunction { A apply(B b); }", - " void test(ImmutableFunction f) {", - " test(new ImmutableFunction<>() {", - " @Override public Integer apply(Integer x) {", - " return xs.get(x);", - " }", - " @SuppressWarnings(\"Immutable\")", - " List xs = new ArrayList<>();", - " });", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + import java.util.ArrayList; + class Test { + @Immutable interface ImmutableFunction { A apply(B b); } + void test(ImmutableFunction f) { + test(new ImmutableFunction<>() { + @Override public Integer apply(Integer x) { + return xs.get(x); + } + @SuppressWarnings("Immutable") + List xs = new ArrayList<>(); + }); + } + } + """) .doTest(); } @@ -2972,22 +3431,23 @@ public void anonymousClass_canCallSuperMethodOnNonImmutableSuperClass() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "import java.util.List;", - "import java.util.ArrayList;", - "class Test {", - " interface Function { default void foo() {} }", - " @Immutable interface ImmutableFunction extends Function { A apply(B b);" - + " }", - " void test(ImmutableFunction f) {", - " test(new ImmutableFunction<>() {", - " @Override public Integer apply(Integer x) {", - " foo();", - " return 0;", - " }", - " });", - " }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + import java.util.List; + import java.util.ArrayList; + class Test { + interface Function { default void foo() {} } + @Immutable interface ImmutableFunction extends Function { A apply(B b); } + void test(ImmutableFunction f) { + test(new ImmutableFunction<>() { + @Override public Integer apply(Integer x) { + foo(); + return 0; + } + }); + } + } + """) .doTest(); } @@ -2997,20 +3457,24 @@ public void switchExpressionsResultingInGenericTypes_doesNotThrow() { compilationHelper .addSourceLines( "Kind.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable enum Kind { A, B; }") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable enum Kind { A, B; } + """) .addSourceLines( "Test.java", - "import java.util.Optional;", - "import java.util.function.Supplier;", - "class Test {", - " Supplier> test(Kind kind) {", - " return switch (kind) {", - " case A -> Optional::empty;", - " case B -> () -> Optional.of(\"\");", - " };", - " }", - "}") + """ + import java.util.Optional; + import java.util.function.Supplier; + class Test { + Supplier> test(Kind kind) { + return switch (kind) { + case A -> Optional::empty; + case B -> () -> Optional.of(""); + }; + } + } + """) .doTest(); } @@ -3020,17 +3484,19 @@ public void switchExpressionsYieldStatement_doesNotThrow() { compilationHelper .addSourceLines( "Test.java", - "import java.util.function.Supplier;", - "class Test {", - " String test(String mode) {", - " return switch (mode) {", - " case \"random\" -> {", - " yield \"foo\";", - " }", - " default -> throw new IllegalArgumentException();", - " };", - " }", - "}") + """ + import java.util.function.Supplier; + class Test { + String test(String mode) { + return switch (mode) { + case "random" -> { + yield "foo"; + } + default -> throw new IllegalArgumentException(); + }; + } + } + """) .doTest(); } @@ -3040,15 +3506,17 @@ public void switchExpressionsMethodReference_doesNotThrow() { compilationHelper .addSourceLines( "Test.java", - "import java.util.function.Supplier;", - "class Test {", - " Supplier test(String mode) {", - " return switch (mode) {", - " case \"random\" -> Math::random;", - " default -> throw new IllegalArgumentException();", - " };", - " }", - "}") + """ + import java.util.function.Supplier; + class Test { + Supplier test(String mode) { + return switch (mode) { + case "random" -> Math::random; + default -> throw new IllegalArgumentException(); + }; + } + } + """) .doTest(); } @@ -3058,17 +3526,19 @@ public void switchExpressionsYieldStatementMethodReference_doesNotThrow() { compilationHelper .addSourceLines( "Test.java", - "import java.util.function.Supplier;", - "class Test {", - " Supplier test(String mode) {", - " return switch (mode) {", - " case \"random\" -> {", - " yield Math::random;", - " }", - " default -> throw new IllegalArgumentException();", - " };", - " }", - "}") + """ + import java.util.function.Supplier; + class Test { + Supplier test(String mode) { + return switch (mode) { + case "random" -> { + yield Math::random; + } + default -> throw new IllegalArgumentException(); + }; + } + } + """) .doTest(); } @@ -3077,11 +3547,13 @@ public void enumBound() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test> {", - " private final E e;", - " Test(E e) { this.e = e; }", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test> { + private final E e; + Test(E e) { this.e = e; } + } + """) .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableRefactoringTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableRefactoringTest.java index 5fdd9b7ae1e..df45b064eb2 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableRefactoringTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ImmutableRefactoringTest.java @@ -34,18 +34,22 @@ public void positive() { compilationHelper .addInputLines( "Test.java", - "import javax.annotation.concurrent.Immutable;", - "@Immutable class Test {", - " final int a = 42;", - " final String b = null;", - "}") + """ + import javax.annotation.concurrent.Immutable; + @Immutable class Test { + final int a = 42; + final String b = null; + } + """) .addOutputLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final int a = 42;", - " final String b = null;", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final int a = 42; + final String b = null; + } + """) .doTest(); } @@ -54,13 +58,15 @@ public void someImmutableSomeNot() { compilationHelper .addInputLines( "Test.java", - "import javax.annotation.concurrent.Immutable;", - "@Immutable class Test {", - " int a = 42;", - " @Immutable static class Inner {", - " final int a = 43;", - " }", - "}") + """ + import javax.annotation.concurrent.Immutable; + @Immutable class Test { + int a = 42; + @Immutable static class Inner { + final int a = 43; + } + } + """) .addOutputLines( "Test.java", "import com.google.errorprone.annotations.Immutable;", @@ -81,10 +87,12 @@ public void negative() { compilationHelper .addInputLines( "Test.java", - "import javax.annotation.concurrent.Immutable;", - "@Immutable class Test {", - " int a = 42;", - "}") + """ + import javax.annotation.concurrent.Immutable; + @Immutable class Test { + int a = 42; + } + """) .addOutputLines( "Test.java", "import com.google.errorprone.annotations.Immutable;", @@ -101,13 +109,15 @@ public void negative_multipleClasses() { compilationHelper .addInputLines( "Test.java", - "import javax.annotation.concurrent.Immutable;", - "@Immutable class Test {", - " int a = 42;", - " @Immutable static class Inner {", - " int a = 43;", - " }", - "}") + """ + import javax.annotation.concurrent.Immutable; + @Immutable class Test { + int a = 42; + @Immutable static class Inner { + int a = 43; + } + } + """) .addOutputLines( "Test.java", "import com.google.errorprone.annotations.Immutable;", diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ThreadSafeCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ThreadSafeCheckerTest.java index 323a3e9f114..764738a7f77 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ThreadSafeCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/ThreadSafeCheckerTest.java @@ -51,20 +51,22 @@ public void basicFields() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.concurrent.ConcurrentMap;", - "import java.util.concurrent.atomic.AtomicLong;", - "@ThreadSafe class Test {", - " final int a = 42;", - " final String b = null;", - " final java.lang.String c = null;", - " final com.google.common.collect.ImmutableList d = null;", - " final ImmutableList e = null;", - " final Deprecated dep = null;", - " final Class clazz = Class.class;", - " final ConcurrentMap concurrentMap = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.ThreadSafe; + import java.util.concurrent.ConcurrentMap; + import java.util.concurrent.atomic.AtomicLong; + @ThreadSafe class Test { + final int a = 42; + final String b = null; + final java.lang.String c = null; + final com.google.common.collect.ImmutableList d = null; + final ImmutableList e = null; + final Deprecated dep = null; + final Class clazz = Class.class; + final ConcurrentMap concurrentMap = null; + } + """) .doTest(); } @@ -91,13 +93,17 @@ public void refactoringWithNameClash() { "@com.google.errorprone.annotations.ThreadSafe interface I {}") .expectUnchanged() .addInputLines( - "ThreadSafe.java", // - "class ThreadSafe implements I {", - "}") + "ThreadSafe.java", + """ + class ThreadSafe implements I { + } + """) .addOutputLines( "ThreadSafe.java", - "@com.google.errorprone.annotations.ThreadSafe class ThreadSafe implements I {", - "}") + """ + @com.google.errorprone.annotations.ThreadSafe class ThreadSafe implements I { + } + """) .doTest(); } @@ -106,8 +112,10 @@ public void annotationsCanBeAnnotatedWithThreadSafe() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe @interface Test {}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe @interface Test {} + """) .doTest(); } @@ -116,19 +124,23 @@ public void customAnnotationsMightBeMutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe @interface Test {}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe @interface Test {} + """) .addSourceLines( "MyTest.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.lang.annotation.Annotation;", - "@ThreadSafe final class MyTest implements Test {", - " // BUG: Diagnostic contains: should be final or annotated", - " public Object[] xs = {};", - " public Class annotationType() {", - " return null;", - " }", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import java.lang.annotation.Annotation; + @ThreadSafe final class MyTest implements Test { + // BUG: Diagnostic contains: should be final or annotated + public Object[] xs = {}; + public Class annotationType() { + return null; + } + } + """) .doTest(); } @@ -137,19 +149,23 @@ public void customAnnotationsSubtype() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe @interface Test {}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe @interface Test {} + """) .addSourceLines( "MyTest.java", - "import java.lang.annotation.Annotation;", - "// BUG: Diagnostic contains:", - "// extends @ThreadSafe type Test, but is not annotated as threadsafe", - "final class MyTest implements Test {", - " public Object[] xs = {};", - " public Class annotationType() {", - " return null;", - " }", - "}") + """ + import java.lang.annotation.Annotation; + // BUG: Diagnostic contains: + // extends @ThreadSafe type Test, but is not annotated as threadsafe + final class MyTest implements Test { + public Object[] xs = {}; + public Class annotationType() { + return null; + } + } + """) .doTest(); } @@ -158,11 +174,13 @@ public void annotationsDefaultToImmutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import javax.lang.model.element.ElementKind;", - "@ThreadSafe class Test {", - " private final Override override = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import javax.lang.model.element.ElementKind; + @ThreadSafe class Test { + private final Override override = null; + } + """) .doTest(); } @@ -171,11 +189,13 @@ public void enumsDefaultToImmutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import javax.lang.model.element.ElementKind;", - "@ThreadSafe class Test {", - " private final ElementKind ek = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import javax.lang.model.element.ElementKind; + @ThreadSafe class Test { + private final ElementKind ek = null; + } + """) .doTest(); } @@ -184,14 +204,18 @@ public void enumsMayBeImmutable() { compilationHelper .addSourceLines( "Kind.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe enum Kind { A, B, C; }") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe enum Kind { A, B, C; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " private final Kind k = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + private final Kind k = null; + } + """) .doTest(); } @@ -200,11 +224,13 @@ public void mutableArray() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains:", - " final int[] xs = {42};", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + // BUG: Diagnostic contains: + final int[] xs = {42}; + } + """) .doTest(); } @@ -213,10 +239,12 @@ public void immutableAnnotatedNotTested() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test {", - " final int[] xs = {42};", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test { + final int[] xs = {42}; + } + """) .doTest(); } @@ -225,13 +253,17 @@ public void immutableAnnotatedNotTested_inheritance() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface Test {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable interface Test {} + """) .addSourceLines( "MyTest.java", - "final class MyTest implements Test {", - " public Object[] xs = {};", - "}") + """ + final class MyTest implements Test { + public Object[] xs = {}; + } + """) .doTest(); } @@ -240,8 +272,10 @@ public void annotatedThreadSafeInterfaces() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe interface Test {}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe interface Test {} + """) .doTest(); } @@ -250,14 +284,18 @@ public void threadSafeInterfaceField() { compilationHelper .addSourceLines( "MyInterface.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe interface MyInterface {}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe interface MyInterface {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " final MyInterface i = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + final MyInterface i = null; + } + """) .doTest(); } @@ -266,14 +304,18 @@ public void immutableInterfaceField() { compilationHelper .addSourceLines( "MyInterface.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable interface MyInterface {}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable interface MyInterface {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " final MyInterface i = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + final MyInterface i = null; + } + """) .doTest(); } @@ -282,11 +324,13 @@ public void deeplyImmutableArguments() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " final ImmutableList>> l = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + final ImmutableList>> l = null; + } + """) .doTest(); } @@ -295,14 +339,16 @@ public void deeplyThreadsafeArguments() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.concurrent.ConcurrentMap;", - "import java.util.concurrent.atomic.AtomicInteger;", - "@ThreadSafe class Test {", - " final ConcurrentMap>> l = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.ThreadSafe; + import java.util.concurrent.ConcurrentMap; + import java.util.concurrent.atomic.AtomicInteger; + @ThreadSafe class Test { + final ConcurrentMap>> l = null; + } + """) .doTest(); } @@ -311,11 +357,13 @@ public void mutableNonFinalField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: should be final or annotated", - " int a = 42;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + // BUG: Diagnostic contains: should be final or annotated + int a = 42; + } + """) .doTest(); } @@ -324,13 +372,15 @@ public void mutableStaticFields() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.List;", - "import java.util.Map;", - "@ThreadSafe class Test {", - " static int a = 42;", - " static final Map> b = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import java.util.List; + import java.util.Map; + @ThreadSafe class Test { + static int a = 42; + static final Map> b = null; + } + """) .doTest(); } @@ -339,15 +389,17 @@ public void mutableFieldGuardedByJsr305Annotation() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.List;", - "import java.util.Map;", - "import javax.annotation.concurrent.GuardedBy;", - "@ThreadSafe class Test {", - " @GuardedBy(\"this\") int a = 42;", - " @GuardedBy(\"this\") final Map> b = null;", - " @GuardedBy(\"this\") volatile int c = 42;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import java.util.List; + import java.util.Map; + import javax.annotation.concurrent.GuardedBy; + @ThreadSafe class Test { + @GuardedBy("this") int a = 42; + @GuardedBy("this") final Map> b = null; + @GuardedBy("this") volatile int c = 42; + } + """) .doTest(); } @@ -356,15 +408,17 @@ public void mutableFieldGuardedByErrorProneAnnotation() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import com.google.errorprone.annotations.concurrent.GuardedBy;", - "import java.util.List;", - "import java.util.Map;", - "@ThreadSafe class Test {", - " @GuardedBy(\"this\") int a = 42;", - " @GuardedBy(\"this\") final Map> b = null;", - " @GuardedBy(\"this\") volatile int c = 42;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import com.google.errorprone.annotations.concurrent.GuardedBy; + import java.util.List; + import java.util.Map; + @ThreadSafe class Test { + @GuardedBy("this") int a = 42; + @GuardedBy("this") final Map> b = null; + @GuardedBy("this") volatile int c = 42; + } + """) .doTest(); } @@ -373,12 +427,14 @@ public void mutableFieldNotGuarded() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import javax.annotation.concurrent.GuardedBy;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: @GuardedBy", - " volatile int a = 42;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import javax.annotation.concurrent.GuardedBy; + @ThreadSafe class Test { + // BUG: Diagnostic contains: @GuardedBy + volatile int a = 42; + } + """) .doTest(); } @@ -387,12 +443,14 @@ public void mutableField() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.Map;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains:", - " final Map a = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import java.util.Map; + @ThreadSafe class Test { + // BUG: Diagnostic contains: + final Map a = null; + } + """) .doTest(); } @@ -401,13 +459,15 @@ public void deeplyMutableTypeArguments() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.Map;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: instantiated with non-thread-safe type for 'E'", - " final ImmutableList>>> l = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.ThreadSafe; + import java.util.Map; + @ThreadSafe class Test { + // BUG: Diagnostic contains: instantiated with non-thread-safe type for 'E' + final ImmutableList>>> l = null; + } + """) .doTest(); } @@ -416,12 +476,14 @@ public void rawImpliesImmutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: was raw", - " final ImmutableList l = null;", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + // BUG: Diagnostic contains: was raw + final ImmutableList l = null; + } + """) .doTest(); } @@ -430,15 +492,19 @@ public void extendsThreadSafe() { compilationHelper .addSourceLines( "Super.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe public class Super {", - " public final int x = 42;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe public class Super { + public final int x = 42; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test extends Super {", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test extends Super { + } + """) .doTest(); } @@ -447,15 +513,19 @@ public void extendsThreadSafe_annotatedWithImmutable() { compilationHelper .addSourceLines( "Super.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe public class Super {", - " public final int x = 42;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe public class Super { + public final int x = 42; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.Immutable;", - "@Immutable class Test extends Super {", - "}") + """ + import com.google.errorprone.annotations.Immutable; + @Immutable class Test extends Super { + } + """) .doTest(); } @@ -463,16 +533,20 @@ public void extendsThreadSafe_annotatedWithImmutable() { public void extendsMutable() { compilationHelper .addSourceLines( - "Super.java", // - "public class Super {", - " public int x = 42;", - "}") + "Super.java", + """ + public class Super { + public int x = 42; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "// BUG: Diagnostic contains: 'Super' has non-final field 'x'", - "@ThreadSafe class Test extends Super {", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + // BUG: Diagnostic contains: 'Super' has non-final field 'x' + @ThreadSafe class Test extends Super { + } + """) .doTest(); } @@ -481,17 +555,21 @@ public void mutableTypeArgumentInstantiation() { compilationHelper .addSourceLines( "Holder.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "public class Holder {", - " public final T t = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + public class Holder { + public final T t = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains:", - " final Holder h = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + // BUG: Diagnostic contains: + final Holder h = null; + } + """) .doTest(); } @@ -500,17 +578,21 @@ public void instantiationWithMutableType() { compilationHelper .addSourceLines( "Holder.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "public class Holder {", - " public final T t = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + public class Holder { + public final T t = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: not annotated", - " final Holder h = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + // BUG: Diagnostic contains: not annotated + final Holder h = null; + } + """) .doTest(); } @@ -519,12 +601,14 @@ public void missingContainerOf() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.List;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: 'T' is a non-thread-safe type variable", - " private final T t = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import java.util.List; + @ThreadSafe class Test { + // BUG: Diagnostic contains: 'T' is a non-thread-safe type variable + private final T t = null; + } + """) .doTest(); } @@ -533,15 +617,19 @@ public void mutableInstantiation() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "public class X { final ImmutableList xs = null; }") + """ + import com.google.common.collect.ImmutableList; + public class X { final ImmutableList xs = null; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - "// BUG: Diagnostic contains:", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + // BUG: Diagnostic contains: + final X x = null; + } + """) .doTest(); } @@ -550,16 +638,20 @@ public void immutableInstantiation_superBound() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "public class X { final ImmutableList xs = null; }") + """ + import com.google.common.collect.ImmutableList; + public class X { final ImmutableList xs = null; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.List;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains:", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import java.util.List; + @ThreadSafe class Test { + // BUG: Diagnostic contains: + final X x = null; + } + """) .doTest(); } @@ -568,16 +660,20 @@ public void mutableInstantiation_superBound() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "public class X { final ImmutableList xs = null; }") + """ + import com.google.common.collect.ImmutableList; + public class X { final ImmutableList xs = null; } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.List;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: is not annotated", - " final X x = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import java.util.List; + @ThreadSafe class Test { + // BUG: Diagnostic contains: is not annotated + final X x = null; + } + """) .doTest(); } @@ -585,22 +681,28 @@ public void mutableInstantiation_superBound() { public void mutableInstantiation_inferredImmutableType() { compilationHelper .addSourceLines( - "X.java", // - "public class X {", - " final T xs = null;", - "}") - .addSourceLines( - "Y.java", // - "public class Y {", - " final X xs = null;", - "}") + "X.java", + """ + public class X { + final T xs = null; + } + """) + .addSourceLines( + "Y.java", + """ + public class Y { + final X xs = null; + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains:", - " final Y x = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + // BUG: Diagnostic contains: + final Y x = null; + } + """) .doTest(); } @@ -609,11 +711,13 @@ public void testImmutableListImplementation() { compilationHelper .addSourceLines( "com/google/common/collect/ImmutableList.java", - "package com.google.common.collect;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class ImmutableList {", - " public Object[] veryMutable = null;", - "}") + """ + package com.google.common.collect; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class ImmutableList { + public Object[] veryMutable = null; + } + """) .doTest(); } @@ -622,23 +726,27 @@ public void positiveAnonymous() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "class Test {{", - " new Super() {", - " // BUG: Diagnostic contains: should be final or annotated", - " int x = 0;", - " {", - " x++;", - " }", - " };", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + class Test {{ + new Super() { + // BUG: Diagnostic contains: should be final or annotated + int x = 0; + { + x++; + } + }; + }} + """) .doTest(); } @@ -647,23 +755,27 @@ public void positiveAnonymousInterface() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe interface Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe interface Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "class Test {{", - " new Super() {", - " // BUG: Diagnostic contains: should be final or annotated", - " int x = 0;", - " {", - " x++;", - " }", - " };", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + class Test {{ + new Super() { + // BUG: Diagnostic contains: should be final or annotated + int x = 0; + { + x++; + } + }; + }} + """) .doTest(); } @@ -674,17 +786,21 @@ public void positive() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "class Test extends Super {", - " // BUG: Diagnostic contains: should be final or annotated", - " public int x = 0;", - "}") + """ + package threadsafety; + class Test extends Super { + // BUG: Diagnostic contains: should be final or annotated + public int x = 0; + } + """) .doTest(); } @@ -693,16 +809,20 @@ public void negative() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test extends Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test extends Super { + } + """) .doTest(); } @@ -713,23 +833,29 @@ public void transitive() { compilationHelper .addSourceLines( "threadsafety/I.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe interface I {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe interface I { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "// BUG: Diagnostic contains: extends @ThreadSafe", - "class Test implements J {", - " public int x = 0;", - "}") + """ + package threadsafety; + // BUG: Diagnostic contains: extends @ThreadSafe + class Test implements J { + public int x = 0; + } + """) .addSourceLines( "threadsafety/J.java", - "package threadsafety;", - "// BUG: Diagnostic contains: extends @ThreadSafe", - "interface J extends I {", - "}") + """ + package threadsafety; + // BUG: Diagnostic contains: extends @ThreadSafe + interface J extends I { + } + """) .doTest(); } @@ -740,17 +866,21 @@ public void negativeAnonymous() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Super {", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Super { + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "class Test {{", - " new Super() {};", - "}}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + class Test {{ + new Super() {}; + }} + """) .doTest(); } @@ -759,24 +889,28 @@ public void positiveEnumConstant() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe interface Super {", - " int f();", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe interface Super { + int f(); + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe enum Test implements Super {", - " INSTANCE {", - " // BUG: Diagnostic contains: should be final or annotated", - " public int x = 0;", - " public int f() {", - " return x++;", - " }", - " }", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe enum Test implements Super { + INSTANCE { + // BUG: Diagnostic contains: should be final or annotated + public int x = 0; + public int f() { + return x++; + } + } + } + """) .doTest(); } @@ -785,21 +919,25 @@ public void negativeEnumConstant() { compilationHelper .addSourceLines( "threadsafety/Super.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe interface Super {", - " void f();", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe interface Super { + void f(); + } + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe enum Test implements Super {", - " INSTANCE {", - " public void f() {", - " }", - " }", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe enum Test implements Super { + INSTANCE { + public void f() { + } + } + } + """) .doTest(); } @@ -822,10 +960,12 @@ public void immutableNull() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " final int[] xs = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + final int[] xs = null; + } + """) .doTest(); } @@ -834,13 +974,15 @@ public void twoFieldsInSource() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: arrays are not thread-safe", - " final int[] xs = {1};", - " // BUG: Diagnostic contains: arrays are not thread-safe", - " final int[] ys = {1};", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + // BUG: Diagnostic contains: arrays are not thread-safe + final int[] xs = {1}; + // BUG: Diagnostic contains: arrays are not thread-safe + final int[] ys = {1}; + } + """) .doTest(); } @@ -849,15 +991,17 @@ public void protosNotOnClasspath() { compilationHelper .addSourceLines( "com/google/errorprone/annotations/ThreadSafe.java", - "package com.google.errorprone.annotations;", - "import static java.lang.annotation.ElementType.TYPE;", - "import static java.lang.annotation.RetentionPolicy.RUNTIME;", - "import java.lang.annotation.Retention;", - "import java.lang.annotation.Target;", - "@Target(TYPE)", - "@Retention(RUNTIME)", - "public @interface ThreadSafe {", - "}") + """ + package com.google.errorprone.annotations; + import static java.lang.annotation.ElementType.TYPE; + import static java.lang.annotation.RetentionPolicy.RUNTIME; + import java.lang.annotation.Retention; + import java.lang.annotation.Target; + @Target(TYPE) + @Retention(RUNTIME) + public @interface ThreadSafe { + } + """) .addSourceLines("Foo.java", "class Foo {}") .addSourceLines( "Test.java", @@ -876,17 +1020,18 @@ public void mutableEnclosing() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "public class Test {", - " int x = 0;", - " // BUG: Diagnostic contains: 'Inner' has non-thread-safe " - + "enclosing instance 'Test'", - " @ThreadSafe public class Inner {", - " public int count() {", - " return x++;", - " }", - " }", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + public class Test { + int x = 0; + // BUG: Diagnostic contains: 'Inner' has non-thread-safe enclosing instance 'Test' + @ThreadSafe public class Inner { + public int count() { + return x++; + } + } + } + """) .doTest(); } @@ -915,11 +1060,13 @@ public void lazyInit() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import com.google.errorprone.annotations.concurrent.LazyInit;", - "@ThreadSafe class Test {", - " @LazyInit int a = 42;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import com.google.errorprone.annotations.concurrent.LazyInit; + @ThreadSafe class Test { + @LazyInit int a = 42; + } + """) .doTest(); } @@ -928,13 +1075,15 @@ public void lazyInitMutable() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import com.google.errorprone.annotations.concurrent.LazyInit;", - "import java.util.List;", - "@ThreadSafe class Test {", - " // BUG: Diagnostic contains: 'List' is not thread-safe", - " @LazyInit List a = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import com.google.errorprone.annotations.concurrent.LazyInit; + import java.util.List; + @ThreadSafe class Test { + // BUG: Diagnostic contains: 'List' is not thread-safe + @LazyInit List a = null; + } + """) .doTest(); } @@ -943,10 +1092,12 @@ public void rawClass() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " final Class clazz = Test.class;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + final Class clazz = Test.class; + } + """) .doTest(); } @@ -956,20 +1107,24 @@ public void threadSafeTypeParam() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.ThreadSafe;", - "public class X {", - " final ImmutableList<@ThreadSafeTypeParameter ?> unknownSafeType;", - " X (ImmutableList<@ThreadSafeTypeParameter ?> unknownSafeType) {", - " this.unknownSafeType = unknownSafeType;", - " }", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.ThreadSafe; + public class X { + final ImmutableList<@ThreadSafeTypeParameter ?> unknownSafeType; + X (ImmutableList<@ThreadSafeTypeParameter ?> unknownSafeType) { + this.unknownSafeType = unknownSafeType; + } + } + """) .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "class Test {", - " final X badX = new X(ImmutableList.of(ImmutableList.of()));", - "}") + """ + import com.google.common.collect.ImmutableList; + class Test { + final X badX = new X(ImmutableList.of(ImmutableList.of())); + } + """) .doTest(); } @@ -979,22 +1134,26 @@ public void mutableTypeParam() { compilationHelper .addSourceLines( "X.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.ThreadSafe;", - "public class X {", - " final ImmutableList<@ThreadSafe ?> unknownSafeType;", - " X (ImmutableList<@ThreadSafe ?> unknownSafeType) {", - " this.unknownSafeType = unknownSafeType;", - " }", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.ThreadSafe; + public class X { + final ImmutableList<@ThreadSafe ?> unknownSafeType; + X (ImmutableList<@ThreadSafe ?> unknownSafeType) { + this.unknownSafeType = unknownSafeType; + } + } + """) .addSourceLines( "Test.java", - "import java.util.ArrayList;", - "import com.google.common.collect.ImmutableList;", - "class Test {", - "// BUG: Diagnostic contains:", - " final X badX = new X(ImmutableList.of(new ArrayList()));", - "}") + """ + import java.util.ArrayList; + import com.google.common.collect.ImmutableList; + class Test { + // BUG: Diagnostic contains: + final X badX = new X(ImmutableList.of(new ArrayList())); + } + """) .doTest(); } @@ -1013,14 +1172,20 @@ public void knownThreadSafeFlag() { CompilationTestHelper.newInstance(ThreadSafeChecker.class, getClass()) .setArgs(ImmutableList.of("-XepOpt:ThreadSafe:KnownThreadSafe=threadsafety.SomeImmutable")) .addSourceLines( - "threadsafety/SomeImmutable.java", "package threadsafety;", "class SomeImmutable {}") + "threadsafety/SomeImmutable.java", + """ + package threadsafety; + class SomeImmutable {} + """) .addSourceLines( "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " public final SomeImmutable s = new SomeImmutable();", - "}") + """ + package threadsafety; + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + public final SomeImmutable s = new SomeImmutable(); + } + """) .doTest(); } @@ -1029,11 +1194,13 @@ public void threadSafeTypeParameter() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import com.google.errorprone.annotations.ThreadSafeTypeParameter;", - "@ThreadSafe class Test<@ThreadSafeTypeParameter T> {", - " final T t = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import com.google.errorprone.annotations.ThreadSafeTypeParameter; + @ThreadSafe class Test<@ThreadSafeTypeParameter T> { + final T t = null; + } + """) .doTest(); } @@ -1042,22 +1209,25 @@ public void threadSafeTypeParameterInstantiation() { compilationHelper .addSourceLines( "A.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import com.google.errorprone.annotations.ThreadSafeTypeParameter;", - "@ThreadSafe class A<@ThreadSafeTypeParameter T> {", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import com.google.errorprone.annotations.ThreadSafeTypeParameter; + @ThreadSafe class A<@ThreadSafeTypeParameter T> { + } + """) .addSourceLines( "Test.java", - "class Test {", - " A f() {", - " return new A<>();", - " }", - " A g() {", - " // BUG: Diagnostic contains: instantiation of 'T' is not " - + "thread-safe, 'Object' is not thread-safe", - " return new A<>();", - " }", - "}") + """ +class Test { + A f() { + return new A<>(); + } + A g() { + // BUG: Diagnostic contains: instantiation of 'T' is not thread-safe, 'Object' is not thread-safe + return new A<>(); + } +} +""") .doTest(); } @@ -1066,10 +1236,12 @@ public void threadSafeTypeParameterUsage() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafeTypeParameter;", - "class Test {", - " static <@ThreadSafeTypeParameter T> void f() {}", - "}") + """ + import com.google.errorprone.annotations.ThreadSafeTypeParameter; + class Test { + static <@ThreadSafeTypeParameter T> void f() {} + } + """) .doTest(); } @@ -1078,10 +1250,12 @@ public void threadSafeTypeParameterUsage_interface() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import com.google.errorprone.annotations.ThreadSafeTypeParameter;", - "@ThreadSafe interface Test<@ThreadSafeTypeParameter T> {", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + import com.google.errorprone.annotations.ThreadSafeTypeParameter; + @ThreadSafe interface Test<@ThreadSafeTypeParameter T> { + } + """) .doTest(); } @@ -1090,9 +1264,11 @@ public void threadSafeTypeParameterMutableClass() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafeTypeParameter;", - "// BUG: Diagnostic contains: @ThreadSafeTypeParameter is only supported on", - "class A<@ThreadSafeTypeParameter T> {}") + """ + import com.google.errorprone.annotations.ThreadSafeTypeParameter; + // BUG: Diagnostic contains: @ThreadSafeTypeParameter is only supported on + class A<@ThreadSafeTypeParameter T> {} + """) .doTest(); } @@ -1101,12 +1277,14 @@ public void annotatedClassType() { compilationHelper .addSourceLines( "Test.java", - "import static java.lang.annotation.ElementType.TYPE_USE;", - "import java.lang.annotation.Target;", - "@Target(TYPE_USE) @interface A {}", - "class Test {", - " Object o = new @A Object();", - "}") + """ + import static java.lang.annotation.ElementType.TYPE_USE; + import java.lang.annotation.Target; + @Target(TYPE_USE) @interface A {} + class Test { + Object o = new @A Object(); + } + """) .doTest(); } @@ -1115,12 +1293,14 @@ public void instantiationWithThreadSafeTypeParameter() { compilationHelper .addSourceLines( "Test.java", - "import com.google.common.collect.ImmutableList;", - "import com.google.errorprone.annotations.ThreadSafe;", - "import com.google.errorprone.annotations.ThreadSafeTypeParameter;", - "@ThreadSafe public class Test<@ThreadSafeTypeParameter T> {", - " final ImmutableList xs = ImmutableList.of();", - "}") + """ + import com.google.common.collect.ImmutableList; + import com.google.errorprone.annotations.ThreadSafe; + import com.google.errorprone.annotations.ThreadSafeTypeParameter; + @ThreadSafe public class Test<@ThreadSafeTypeParameter T> { + final ImmutableList xs = ImmutableList.of(); + } + """) .doTest(); } @@ -1130,19 +1310,21 @@ public void notAllTypeVarsInstantiated() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafeTypeParameter;", - "import java.util.function.Function;", - "class Test {", - " public final void f1(A transform) {}", - " public C f2(Function fn) {", - " return null;", - " }", - " public final void f3(Function fn) {", - " // BUG: Diagnostic contains: instantiation of 'C' is not thread-safe", - " // 'E' is a non-thread-safe type variable", - " f1(f2(fn));", - " }", - "}") + """ + import com.google.errorprone.annotations.ThreadSafeTypeParameter; + import java.util.function.Function; + class Test { + public final void f1(A transform) {} + public C f2(Function fn) { + return null; + } + public final void f3(Function fn) { + // BUG: Diagnostic contains: instantiation of 'C' is not thread-safe + // 'E' is a non-thread-safe type variable + f1(f2(fn)); + } + } + """) .doTest(); } @@ -1154,19 +1336,21 @@ public void notAllTypeVarsInstantiated_shouldFail() { compilationHelper .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafeTypeParameter;", - "import java.util.function.Function;", - "class Test {", - " public final void f1(A transform) {}", - " public <@ThreadSafeTypeParameter B, C> C f2(Function fn) {", - " return null;", - " }", - " public final void f3(Function fn) {", - " // BUG: Diagnostic contains: instantiation of 'B' is not thread-safe", - " // 'D' is a non-thread-safe type variable", - " f1(f2(fn));", - " }", - "}") + """ + import com.google.errorprone.annotations.ThreadSafeTypeParameter; + import java.util.function.Function; + class Test { + public final void f1(A transform) {} + public <@ThreadSafeTypeParameter B, C> C f2(Function fn) { + return null; + } + public final void f3(Function fn) { + // BUG: Diagnostic contains: instantiation of 'B' is not thread-safe + // 'D' is a non-thread-safe type variable + f1(f2(fn)); + } + } + """) .doTest(); } @@ -1175,14 +1359,18 @@ public void threadSafeUpperBound() { compilationHelper .addSourceLines( "MyThreadSafeType.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class MyThreadSafeType {}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class MyThreadSafeType {} + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " final T x = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + final T x = null; + } + """) .doTest(); } @@ -1191,11 +1379,13 @@ public void threadSafeRecursiveUpperBound() { compilationHelper .addSourceLines( "Recursive.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe", - "abstract class Recursive> {", - " final T x = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe + abstract class Recursive> { + final T x = null; + } + """) .doTest(); } @@ -1204,15 +1394,16 @@ public void threadSafeRecursiveUpperBound_notThreadsafe() { compilationHelper .addSourceLines( "Recursive.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "import java.util.List;", - "@ThreadSafe", - "abstract class Recursive> {", - " final T x = null;", - " // BUG: Diagnostic contains: @ThreadSafe class has " - + "non-thread-safe field, 'List' is not thread-safe", - " final List y = null;", - "}") + """ +import com.google.errorprone.annotations.ThreadSafe; +import java.util.List; +@ThreadSafe +abstract class Recursive> { + final T x = null; + // BUG: Diagnostic contains: @ThreadSafe class has non-thread-safe field, 'List' is not thread-safe + final List y = null; +} +""") .doTest(); } @@ -1221,15 +1412,19 @@ public void protoEnum() { compilationHelper .addSourceLines( "E.java", - "import com.google.protobuf.ProtocolMessageEnum;", - "abstract class E implements ProtocolMessageEnum {", - "}") + """ + import com.google.protobuf.ProtocolMessageEnum; + abstract class E implements ProtocolMessageEnum { + } + """) .addSourceLines( "Test.java", - "import com.google.errorprone.annotations.ThreadSafe;", - "@ThreadSafe class Test {", - " final E x = null;", - "}") + """ + import com.google.errorprone.annotations.ThreadSafe; + @ThreadSafe class Test { + final E x = null; + } + """) .doTest(); } }