Fail on instanceof native JsType interface.

This is considered a programming error as native
JsType interfaces are castable to any type.

Change-Id: Ia5b081a370957504de7186a00f331f8286eef80c
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
index 87d8612..e332910 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
@@ -26,6 +26,8 @@
 import com.google.gwt.dev.jjs.ast.JExpression;
 import com.google.gwt.dev.jjs.ast.JExpressionStatement;
 import com.google.gwt.dev.jjs.ast.JField;
+import com.google.gwt.dev.jjs.ast.JInstanceOf;
+import com.google.gwt.dev.jjs.ast.JInterfaceType;
 import com.google.gwt.dev.jjs.ast.JMember;
 import com.google.gwt.dev.jjs.ast.JMethod;
 import com.google.gwt.dev.jjs.ast.JMethod.JsPropertyAccessorType;
@@ -34,6 +36,7 @@
 import com.google.gwt.dev.jjs.ast.JParameter;
 import com.google.gwt.dev.jjs.ast.JPrimitiveType;
 import com.google.gwt.dev.jjs.ast.JProgram;
+import com.google.gwt.dev.jjs.ast.JReferenceType;
 import com.google.gwt.dev.jjs.ast.JStatement;
 import com.google.gwt.dev.jjs.ast.JType;
 import com.google.gwt.dev.jjs.ast.JVisitor;
@@ -50,10 +53,6 @@
 /**
  * Checks and throws errors for invalid JsInterop constructs.
  */
-// TODO: handle custom JsType field/method names when that feature exists.
-// TODO: move JsInterop checks from JSORestrictionsChecker to here.
-// TODO: provide more information in global name collisions as it could be difficult to pinpoint in
-// big projects.
 public class JsInteropRestrictionChecker {
 
   public static void exec(TreeLogger logger, JProgram jprogram,
@@ -61,7 +60,7 @@
     JsInteropRestrictionChecker jsInteropRestrictionChecker =
         new JsInteropRestrictionChecker(logger, jprogram, minimalRebuildCache);
 
-    jsInteropRestrictionChecker.checkProgram(jprogram);
+    jsInteropRestrictionChecker.checkProgram();
     if (jsInteropRestrictionChecker.hasErrors) {
       throw new UnableToCompleteException();
     }
@@ -93,7 +92,7 @@
    */
   private static boolean isConstructorEmpty(final JConstructor constructor) {
     List<JStatement> statements = FluentIterable
-        .from(((JMethodBody) constructor.getBody()).getStatements())
+        .from(constructor.getBody().getStatements())
         .filter(new Predicate<JStatement>() {
           @Override
           public boolean apply(JStatement statement) {
@@ -378,7 +377,7 @@
     }
   }
 
-  private void checkNoStaticJsPropertyCalls() {
+  private void checkStaticJsPropertyCalls() {
     new JVisitor() {
       @Override
       public boolean visit(JMethod x, Context ctx) {
@@ -399,6 +398,22 @@
     }.accept(jprogram);
   }
 
+  private void checkInstanceOfNativeJsTypes() {
+    new JVisitor() {
+      @Override
+      public boolean visit(JInstanceOf x, Context ctx) {
+        JReferenceType type = x.getTestType();
+        if (type.isJsNative() && type instanceof JInterfaceType) {
+          logError("Cannot do instanceof against native JsType interface %s (%s:%d).",
+              type.getName(),
+              x.getSourceInfo().getFileName(),
+              x.getSourceInfo().getStartLine());
+        }
+        return true;
+      }
+    }.accept(jprogram);
+  }
+
   private void checkNativeJsType(JDeclaredType type) {
     // TODO(rluble): add inheritance restrictions.
     if (type.isEnumOrSubclass() != null) {
@@ -457,11 +472,12 @@
     }
   }
 
-  private void checkProgram(JProgram jprogram) {
+  private void checkProgram() {
     for (JDeclaredType type : jprogram.getModuleDeclaredTypes()) {
       checkType(type);
     }
-    checkNoStaticJsPropertyCalls();
+    checkStaticJsPropertyCalls();
+    checkInstanceOfNativeJsTypes();
   }
 
   private void checkType(JDeclaredType type) {
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
index 3886569..f652546 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
@@ -992,6 +992,18 @@
     assertBuggySucceeds();
   }
 
+  public void testJsTypeInterfaceInInstanceofFails() throws Exception {
+    addSnippetImport("jsinterop.annotations.JsType");
+    addSnippetClassDecl(
+        "@JsType(isNative=true) public interface IBuggy {}",
+        "@JsType public static class Buggy {",
+        "  public Buggy() { if (new Object() instanceof IBuggy) {} }",
+        "}");
+
+    assertBuggyFails("Cannot do instanceof against native JsType interface test.EntryPoint$IBuggy "
+        + "(test/EntryPoint.java:6).");
+  }
+
   public void testNativeJsTypeEnumFails() {
     addSnippetImport("jsinterop.annotations.JsType");
     addSnippetClassDecl(
diff --git a/user/test/com/google/gwt/core/client/interop/JsFunctionTest.java b/user/test/com/google/gwt/core/client/interop/JsFunctionTest.java
index 5e55044..b775f46 100644
--- a/user/test/com/google/gwt/core/client/interop/JsFunctionTest.java
+++ b/user/test/com/google/gwt/core/client/interop/JsFunctionTest.java
@@ -209,7 +209,6 @@
     assertTrue(object instanceof MyJsFunctionIdentityInterface);
     assertTrue(object instanceof MyJsFunctionWithOnlyInstanceofReference);
     assertFalse(object instanceof MyJsFunctionInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
   }
 
   public void testInstanceOf_jsObject() {
@@ -218,7 +217,6 @@
     assertFalse(object instanceof MyJsFunctionIdentityInterface);
     assertFalse(object instanceof MyJsFunctionWithOnlyInstanceofReference);
     assertFalse(object instanceof MyJsFunctionInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
   }
 
   public void testInstanceOf_javaInstance() {
@@ -227,7 +225,6 @@
     assertTrue(object instanceof MyJsFunctionInterfaceImpl);
     assertTrue(object instanceof MyJsFunctionIdentityInterface);
     assertTrue(object instanceof MyJsFunctionWithOnlyInstanceofReference);
-    assertTrue(object instanceof ElementLikeNativeInterface);
     assertFalse(object instanceof HTMLElementConcreteNativeJsType);
   }
 
diff --git a/user/test/com/google/gwt/core/client/interop/JsTypeTest.java b/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
index f84b0f0..7e24cf9 100644
--- a/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
+++ b/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
@@ -15,8 +15,6 @@
  */
 package com.google.gwt.core.client.interop;
 
-import static com.google.gwt.core.client.ScriptInjector.TOP_WINDOW;
-
 import static jsinterop.annotations.JsPackage.GLOBAL;
 
 import com.google.gwt.core.client.JavaScriptObject;
@@ -46,7 +44,8 @@
     ScriptInjector.fromString("function JsTypeTest_MyNativeJsType() {}\n"
         + "JsTypeTest_MyNativeJsType.prototype.sum = "
         + "    function sum(bias) { return this.y + bias; };")
-        .setWindow(TOP_WINDOW).inject();
+        .setWindow(ScriptInjector.TOP_WINDOW)
+        .inject();
   }
 
   public void testVirtualUpRefs() {
@@ -213,12 +212,9 @@
     assertFalse(object instanceof HTMLButtonElement);
     assertFalse(object instanceof HTMLElementConcreteNativeJsType);
     assertFalse(object instanceof Iterator);
-    assertTrue(object instanceof MyNativeJsTypeInterface);
     assertFalse(object instanceof MyNativeJsTypeInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
     assertFalse(object instanceof ElementLikeNativeInterfaceImpl);
     assertFalse(object instanceof MyJsInterfaceWithOnlyInstanceofReference);
-    assertTrue(object instanceof MyNativeJsTypeInterfaceAndOnlyInstanceofReference);
     assertTrue(object instanceof AliasToMyNativeJsTypeWithOnlyInstanceofReference);
     assertFalse(object instanceof ConcreteJsType);
   }
@@ -231,12 +227,9 @@
     assertFalse(object instanceof HTMLButtonElement);
     assertFalse(object instanceof HTMLElementConcreteNativeJsType);
     assertFalse(object instanceof Iterator);
-    assertTrue(object instanceof MyNativeJsTypeInterface);
     assertFalse(object instanceof MyNativeJsTypeInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
     assertFalse(object instanceof ElementLikeNativeInterfaceImpl);
     assertFalse(object instanceof MyJsInterfaceWithOnlyInstanceofReference);
-    assertTrue(object instanceof MyNativeJsTypeInterfaceAndOnlyInstanceofReference);
     assertFalse(object instanceof AliasToMyNativeJsTypeWithOnlyInstanceofReference);
     assertFalse(object instanceof ConcreteJsType);
   }
@@ -249,12 +242,9 @@
     assertTrue(object instanceof HTMLButtonElement);
     assertTrue(object instanceof HTMLElementConcreteNativeJsType);
     assertFalse(object instanceof Iterator);
-    assertTrue(object instanceof MyNativeJsTypeInterface);
     assertFalse(object instanceof MyNativeJsTypeInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
     assertFalse(object instanceof ElementLikeNativeInterfaceImpl);
     assertFalse(object instanceof MyJsInterfaceWithOnlyInstanceofReference);
-    assertTrue(object instanceof MyNativeJsTypeInterfaceAndOnlyInstanceofReference);
     assertFalse(object instanceof AliasToMyNativeJsTypeWithOnlyInstanceofReference);
     assertFalse(object instanceof ConcreteJsType);
   }
@@ -268,12 +258,9 @@
     assertFalse(object instanceof HTMLButtonElement);
     assertFalse(object instanceof HTMLElementConcreteNativeJsType);
     assertFalse(object instanceof Iterator);
-    assertTrue(object instanceof MyNativeJsTypeInterface);
     assertFalse(object instanceof MyNativeJsTypeInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
     assertTrue(object instanceof ElementLikeNativeInterfaceImpl);
     assertFalse(object instanceof MyJsInterfaceWithOnlyInstanceofReference);
-    assertTrue(object instanceof MyNativeJsTypeInterfaceAndOnlyInstanceofReference);
     assertFalse(object instanceof AliasToMyNativeJsTypeWithOnlyInstanceofReference);
     assertFalse(object instanceof ConcreteJsType);
   }
@@ -287,12 +274,9 @@
     assertFalse(object instanceof HTMLButtonElement);
     assertFalse(object instanceof HTMLElementConcreteNativeJsType);
     assertFalse(object instanceof Iterator);
-    assertTrue(object instanceof MyNativeJsTypeInterface);
     assertTrue(object instanceof MyNativeJsTypeInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
     assertFalse(object instanceof ElementLikeNativeInterfaceImpl);
     assertFalse(object instanceof MyJsInterfaceWithOnlyInstanceofReference);
-    assertTrue(object instanceof MyNativeJsTypeInterfaceAndOnlyInstanceofReference);
     assertFalse(object instanceof AliasToMyNativeJsTypeWithOnlyInstanceofReference);
     assertFalse(object instanceof ConcreteJsType);
   }
@@ -306,12 +290,9 @@
     assertFalse(object instanceof HTMLButtonElement);
     assertFalse(object instanceof HTMLElementConcreteNativeJsType);
     assertFalse(object instanceof Iterator);
-    assertTrue(object instanceof MyNativeJsTypeInterface);
     assertFalse(object instanceof MyNativeJsTypeInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
     assertFalse(object instanceof ElementLikeNativeInterfaceImpl);
     assertFalse(object instanceof MyJsInterfaceWithOnlyInstanceofReference);
-    assertTrue(object instanceof MyNativeJsTypeInterfaceAndOnlyInstanceofReference);
     assertFalse(object instanceof AliasToMyNativeJsTypeWithOnlyInstanceofReference);
     assertTrue(object instanceof ConcreteJsType);
   }
@@ -325,12 +306,9 @@
     assertTrue(object instanceof HTMLButtonElement);
     assertTrue(object instanceof HTMLElementConcreteNativeJsType);
     assertTrue(object instanceof Iterable);
-    assertTrue(object instanceof MyNativeJsTypeInterface);
     assertFalse(object instanceof MyNativeJsTypeInterfaceImpl);
-    assertTrue(object instanceof ElementLikeNativeInterface);
     assertFalse(object instanceof ElementLikeNativeInterfaceImpl);
     assertFalse(object instanceof MyJsInterfaceWithOnlyInstanceofReference);
-    assertTrue(object instanceof MyNativeJsTypeInterfaceAndOnlyInstanceofReference);
     assertFalse(object instanceof AliasToMyNativeJsTypeWithOnlyInstanceofReference);
     assertFalse(object instanceof ConcreteJsType);
   }