@Test
 public void testLocked() throws Exception {
   compilationHelper
       .addSourceLines(
           "threadsafety/Test.java",
           "package threadsafety;",
           "import javax.annotation.concurrent.GuardedBy;",
           "import java.util.concurrent.locks.Lock;",
           "class Test {",
           "  final Lock mu = null;",
           "  final Lock lock = null;",
           "  @GuardedBy(\"lock\")",
           "  int x;",
           "  void m() {",
           "    mu.lock();",
           "    // BUG: Diagnostic contains:  []",
           "    x++;",
           "    try {",
           "      // BUG: Diagnostic contains:",
           "      // [(SELECT (THIS) mu)]",
           "      x++;",
           "    } finally {",
           "      mu.unlock();",
           "    }",
           "    // BUG: Diagnostic contains:  []",
           "    x++;",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void uiField() throws Exception {
   compilationHelper
       .addSourceLines(
           "com/google/gwt/uibinder/client/UiField.java",
           "package com.google.gwt.uibinder.client;",
           "public @interface UiField {}")
       .addSourceLines("Box.java", "public class Box<T> {", "  T get() { return null; }", "}")
       .addSourceLines(
           "Widget.java",
           "import com.google.gwt.uibinder.client.UiField;",
           "public class Widget {",
           "  @UiField Box<Boolean> l;",
           "}")
       .addSourceLines(
           "Test.java",
           "import static org.mockito.Mockito.when;",
           "import static org.mockito.Answers.RETURNS_SMART_NULLS;",
           "class Test {",
           "  Widget w;",
           "  void m(Iterable<Boolean> xs) {",
           "    // BUG: Diagnostic contains: when((Object) w.l.get()).thenReturn(null);",
           "    when(w.l.get()).thenReturn(null);",
           "  }",
           "}")
       .doTest();
 }
 // regression test for #418
 @Test
 public void typeParameter() {
   compilationHelper
       .addSourceLines(
           "Nullable.java",
           "import java.lang.annotation.ElementType;",
           "import java.lang.annotation.Retention;",
           "import java.lang.annotation.RetentionPolicy;",
           "import java.lang.annotation.Target;",
           "@Retention(RetentionPolicy.RUNTIME)",
           "@Target(ElementType.TYPE_USE)",
           "public @interface Nullable {}")
       .addSourceLines(
           "Test.java",
           "class Test {",
           "  // BUG: Diagnostic contains:",
           "  @Nullable int x;",
           "  // BUG: Diagnostic contains:",
           "  @Nullable int f() {",
           "    return 42;",
           "  }",
           "  <@Nullable T> int g() {",
           "    return 42;",
           "  }",
           "  int @Nullable [] y;",
           "}")
       .doTest();
 }
 @Test
 public void imported() throws Exception {
   compilationHelper
       .addSourceLines(
           "pkg/Bound.java",
           "package pkg;",
           "public class Bound {",
           "  public static class Inner {}",
           "  public static class Sub extends Inner {}",
           "}")
       .addSourceLines(
           "Foo.java",
           "import pkg.Bound;",
           "public class Foo {",
           "  public <T extends Bound.Inner> T f(Iterable<T> xs) { return xs.iterator().next(); }",
           "}")
       .addSourceLines(
           "Test.java",
           "import static org.mockito.Mockito.when;",
           "import static org.mockito.Answers.RETURNS_SMART_NULLS;",
           "import org.mockito.Mock;",
           "class Test {",
           "  final int ONE = 1;",
           "  final int TWO = 1;",
           "  @Mock(answer = RETURNS_SMART_NULLS) Foo l;",
           "  void m(Iterable<pkg.Bound.Sub> xs) {",
           "    // BUG: Diagnostic contains: when((Bound.Inner) l.f(xs)).thenReturn(null);",
           "    when(l.f(xs)).thenReturn(null);",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void testNegativeCase5() throws Exception {
   compilationHelper
       .addSourceFile("JUnit3TestNotRunNegativeCase3.java") // needed as a dependency
       .addSourceFile("JUnit3TestNotRunNegativeCase5.java")
       .doTest();
 }
 @Test
 public void testNegativeCase() throws Exception {
   compilationHelper.assertCompileSucceeds(
       new File(
           this.getClass()
               .getResource("InjectMoreThanOneScopeAnnotationOnClassNegativeCases.java")
               .toURI()));
 }
 @Test
 public void testPositiveCase() throws Exception {
   compilationHelper.assertCompileFailsWithMessages(
       new File(
           this.getClass()
               .getResource("InjectMoreThanOneScopeAnnotationOnClassPositiveCases.java")
               .toURI()));
 }
 @Test
 public void finalField() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           // TODO(b/21633565): force line break
           "class Test {",
           "  public final int x = 42;",
           "}")
       .doTest();
 }
 @Test
 public void varField() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           "import com.google.errorprone.annotations.Var;",
           "class Test {",
           "  @Var public int x = 42;",
           "}")
       .doTest();
 }
 @Test
 public void interfaceMethod() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           // TODO(b/21633565): force line break
           "interface Test {",
           "  void f(int y);",
           "}")
       .doTest();
 }
 @Test
 public void abstractMethod() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           // TODO(b/21633565): force line break
           "abstract class Test {",
           "  abstract void f(int y);",
           "}")
       .doTest();
 }
 @Test
 public void unnecessaryFinalNativeMethod() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           "class Test {",
           "  // BUG: Diagnostic contains: native void f(int y);",
           "  native void f(final int y);",
           "}")
       .doTest();
 }
 @Test
 public void negativeVoid() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           "import javax.annotation.Nullable;",
           "class Test {",
           "  @Nullable void f() {}",
           "}")
       .doTest();
 }
 @Test
 public void negativeParam() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           // TODO(b/21633565): force line break
           "class Test {",
           "  public void x(int y) {",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void enhancedFor() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           "class Test {",
           "  void f (Iterable<String> xs) {",
           "    for (String x : xs) {",
           "    }",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void forLoop() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           "class Test {",
           "  {",
           "    for (int i = 0; i < 10; i++) {",
           "    }",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void positiveParam() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           "class Test {",
           "  // BUG: Diagnostic contains: public void x(@Var int y) {",
           "  public void x(int y) {",
           "    y++;",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void varParam() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           "import com.google.errorprone.annotations.Var;",
           "class Test {",
           "  public void x(@Var int y) {",
           "    y++;",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void finalLocal7() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           // TODO(b/21633565): force line break
           "class Test {",
           "  public void x() {",
           "    final int y = 0;",
           "  }",
           "}")
       .setArgs(Arrays.asList("-source", "7", "-target", "7"))
       .doTest();
 }
 @Test
 public void finalLocal8() {
   compilationHelper
       .addSourceLines(
           "Test.java",
           "class Test {",
           "  public void x() {",
           "    // BUG: Diagnostic contains: /*START*/ int y = 0;",
           "    /*START*/ final int y = 0;",
           "  }",
           "}")
       .setArgs(Arrays.asList("-source", "8", "-target", "8"))
       .doTest();
 }
 @Test
 public void varInitializedWithUnsupportedAnswer() throws Exception {
   compilationHelper
       .addSourceLines("Box.java", "public class Box<T> {", "  T f() { return null; }", "}")
       .addSourceLines(
           "Test.java",
           "import org.mockito.Mockito;",
           "class Test {",
           "  Box<Boolean> box = Mockito.mock(Box.class, Mockito.RETURNS_SMART_NULLS);",
           "  void m() {",
           "    // BUG: Diagnostic contains: when((Object) box.f()).thenReturn(false);",
           "    Mockito.when(box.f()).thenReturn(false);",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void testSynchronizedMethod() throws Exception {
   compilationHelper
       .addSourceLines(
           "threadsafety/Test.java",
           "package threadsafety;",
           "import javax.annotation.concurrent.GuardedBy;",
           "import java.util.concurrent.locks.Lock;",
           "class Test {",
           "  @GuardedBy(\"this\")",
           "  int x;",
           "  synchronized void m() {",
           "    // BUG: Diagnostic contains:  [(THIS)]",
           "    x++;",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void mockedFieldInstantiationOfGenericType() throws Exception {
   compilationHelper
       .addSourceLines("Super.java", "public class Super<T> {", "  T f() { return null; }", "}")
       .addSourceLines("Sub.java", "public class Sub extends Super<Boolean> {", "}")
       .addSourceLines(
           "Test.java",
           "import static org.mockito.Mockito.when;",
           "import static org.mockito.Answers.RETURNS_SMART_NULLS;",
           "import org.mockito.Mock;",
           "class Test {",
           "  @Mock(answer = RETURNS_SMART_NULLS) Super<Boolean> s;",
           "  void m() {",
           "    // BUG: Diagnostic contains: when((Object) s.f()).thenReturn(false);",
           "    when(s.f()).thenReturn(false);",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void chainedCallOnUnsupportedMock() throws Exception {
   compilationHelper
       .addSourceLines(
           "Foo.java", "public class Foo {", "  Bar<Boolean> bar() { return null; }", "}")
       .addSourceLines("Bar.java", "public class Bar<T> {", "  T get() { return null; }", "}")
       .addSourceLines(
           "Test.java",
           "import static org.mockito.Mockito.when;",
           "import static org.mockito.Answers.RETURNS_SMART_NULLS;",
           "import org.mockito.Mock;",
           "class Test {",
           "  @Mock(answer = RETURNS_SMART_NULLS) Foo f;",
           "  void m() {",
           "    // BUG: Diagnostic contains: when((Object) f.bar().get()).thenReturn(false);",
           "    when(f.bar().get()).thenReturn(false);",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void defaultAnswerOk() throws Exception {
   compilationHelper
       .addSourceLines(
           "Foo.java",
           "public class Foo {",
           "  public <T> T f(Iterable<T> xs) { return xs.iterator().next(); }",
           "}")
       .addSourceLines(
           "Test.java",
           "import static org.mockito.Mockito.when;",
           "import static org.mockito.Answers.RETURNS_SMART_NULLS;",
           "import org.mockito.Mock;",
           "class Test {",
           "  @Mock Foo l;",
           "  void m(Iterable<Boolean> xs) {",
           "    when(l.f(xs)).thenReturn(false);",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void testSynchronizedClass() throws Exception {
   compilationHelper
       .addSourceLines(
           "threadsafety/Test.java",
           "package threadsafety;",
           "import javax.annotation.concurrent.GuardedBy;",
           "class Lock {}",
           "class Test {",
           "  final Lock mu = new Lock();",
           "  @GuardedBy(\"this\")",
           "  int x;",
           "  void m() {",
           "    synchronized (Lock.class) {",
           "      // BUG: Diagnostic contains:  [(CLASS_LITERAL threadsafety.Lock)]",
           "      x++;",
           "    }",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void testLockMethodEnclosingAccess() throws Exception {
   compilationHelper
       .addSourceLines(
           "threadsafety/Test.java",
           "package threadsafety;",
           "import javax.annotation.concurrent.GuardedBy;",
           "import com.google.errorprone.annotations.concurrent.LockMethod;",
           "import com.google.errorprone.annotations.concurrent.UnlockMethod;",
           "import java.util.concurrent.locks.Lock;",
           "class Outer {",
           "  Lock lock;",
           "  class Inner {",
           "    @GuardedBy(\"lock\")",
           "    int x;",
           "    ",
           "    @LockMethod(\"lock\")",
           "    void lock() {",
           "      lock.lock();",
           "    }",
           "    ",
           "    @UnlockMethod(\"lock\")",
           "    void unlock() {",
           "      lock.unlock();",
           "    }",
           "    ",
           "    void m(Inner i) {",
           "      i.lock();",
           "      try {",
           "        // BUG: Diagnostic contains:",
           "        // [(SELECT (SELECT (LOCAL_VARIABLE i) outer$threadsafety.Outer) lock)]",
           "        i.x++;",
           "      } finally {",
           "        i.unlock();",
           "      }",
           "    }",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void testSynchronizedField() throws Exception {
   compilationHelper
       .addSourceLines(
           "threadsafety/Test.java",
           "package threadsafety;",
           "import javax.annotation.concurrent.GuardedBy;",
           "class Lock { final Object lock = null; }",
           "class Test {",
           "  final Lock mu = new Lock();",
           "  @GuardedBy(\"this\")",
           "  int x;",
           "  void m() {",
           "    synchronized (mu.lock) {",
           "      // BUG: Diagnostic contains:",
           "      // [(SELECT (SELECT (THIS) mu) lock)]",
           "      x++;",
           "    }",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void mockAnnotationWithUnsupportedAnswer() throws Exception {
   compilationHelper
       .addSourceLines(
           "Foo.java",
           "public class Foo {",
           "  public <T> T f(Iterable<T> xs) { return xs.iterator().next(); }",
           "}")
       .addSourceLines(
           "Test.java",
           "import static org.mockito.Mockito.when;",
           "import static org.mockito.Answers.RETURNS_SMART_NULLS;",
           "import org.mockito.Mock;",
           "class Test {",
           "  @Mock(answer = RETURNS_SMART_NULLS) Foo l;",
           "  void m(Iterable<Boolean> xs) {",
           "    // BUG: Diagnostic contains: when((Object) l.f(xs)).thenReturn(false);",
           "    when(l.f(xs)).thenReturn(false);",
           "  }",
           "}")
       .doTest();
 }
 @Test
 public void erasureIsNotObject() throws Exception {
   compilationHelper
       .addSourceLines(
           "Super.java",
           "public class Super<T extends Boolean> {",
           "  T f() { return null; }",
           "}")
       .addSourceLines("Sub.java", "public class Sub extends Super<Boolean> {", "}")
       .addSourceLines(
           "Test.java",
           "import static org.mockito.Mockito.when;",
           "import static org.mockito.Answers.RETURNS_SMART_NULLS;",
           "import org.mockito.Mock;",
           "class Test {",
           "  @Mock(answer = RETURNS_SMART_NULLS) Super<Boolean> s;",
           "  void m() {",
           "    when(s.f()).thenReturn(false);",
           "  }",
           "}")
       .doTest();
 }