Add JsPropertyChecks to JsInteropRestrictionChecker.

Change-Id: I9ba1da90676484915c99fdbb350e62c6444d46b6
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 ee338e1..fb3faf9 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
@@ -16,6 +16,7 @@
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.dev.MinimalRebuildCache;
+import com.google.gwt.dev.jjs.ast.Context;
 import com.google.gwt.dev.jjs.ast.JConstructor;
 import com.google.gwt.dev.jjs.ast.JDeclaredType;
 import com.google.gwt.dev.jjs.ast.JExpressionStatement;
@@ -29,6 +30,7 @@
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JStatement;
 import com.google.gwt.dev.jjs.ast.JType;
+import com.google.gwt.dev.jjs.ast.JVisitor;
 import com.google.gwt.thirdparty.guava.common.base.Predicate;
 import com.google.gwt.thirdparty.guava.common.collect.FluentIterable;
 import com.google.gwt.thirdparty.guava.common.collect.Iterables;
@@ -275,6 +277,21 @@
     }
   }
 
+  private void checkNoStaticJsPropertyCalls() {
+    new JVisitor() {
+      @Override
+      public void endVisit(JMethodCall x, Context ctx) {
+        JMethod target = x.getTarget();
+        if (x.isStaticDispatchOnly() && target.isJsPropertyAccessor()) {
+          logError("Cannot call property accessor '%s' via super (%s:%d).",
+              target.getQualifiedName(),
+              x.getSourceInfo().getFileName(),
+              x.getSourceInfo().getStartLine());
+        }
+      }
+    }.accept(jprogram);
+  }
+
   private void checkJsNative(JDeclaredType type) {
     // TODO(rluble): add inheritance restrictions.
     if (!JjsUtils.isClinitEmpty(type)) {
@@ -326,6 +343,7 @@
     for (JDeclaredType type : jprogram.getModuleDeclaredTypes()) {
       checkType(type);
     }
+    checkNoStaticJsPropertyCalls();
   }
 
   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 b5a4bdd..a6e4b10 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
@@ -257,11 +257,11 @@
 
     assertBuggyFails(
         "The JsType member 'test.EntryPoint$IBuggy.x(Z)Z' and JsProperty "
-        + "'test.EntryPoint$IBuggy.setX(I)V' can't both be named 'x' in "
-        + "type 'test.EntryPoint$IBuggy'.",
+            + "'test.EntryPoint$IBuggy.setX(I)V' can't both be named 'x' in "
+            + "type 'test.EntryPoint$IBuggy'.",
         "The JsType member 'test.EntryPoint$Buggy.x(Z)Z' and JsProperty "
-        + "'test.EntryPoint$Buggy.setX(I)V' can't both be named 'x' in "
-        + "type 'test.EntryPoint$Buggy'.");
+            + "'test.EntryPoint$Buggy.setX(I)V' can't both be named 'x' in "
+            + "type 'test.EntryPoint$Buggy'.");
   }
 
   public void testCollidingMethodExportsFails() throws Exception {
@@ -276,7 +276,7 @@
 
     assertBuggyFails(
         "Member 'test.EntryPoint$Buggy.display()V' can't be exported "
-        + "because the global name 'test.EntryPoint.Buggy.show' is already taken.");
+            + "because the global name 'test.EntryPoint.Buggy.show' is already taken.");
   }
 
   public void testCollidingMethodToFieldExportsFails() throws Exception {
@@ -637,6 +637,59 @@
         + "'test.EntryPoint$Exported' is not a JsType.");
   }
 
+  public void testJsPropertySuperCallFails()
+      throws UnableToCompleteException {
+    addSnippetImport("com.google.gwt.core.client.js.JsType");
+    addSnippetImport("com.google.gwt.core.client.js.JsProperty");
+    addSnippetClassDecl(
+        "@JsType public static class Super {",
+        "  @JsProperty public int getX() { return 5; }",
+        "}",
+        "@JsType public static class Buggy extends Super {",
+        "  public int m() { return super.getX(); }",
+        "}");
+
+    assertBuggyFails(
+        "Cannot call property accessor 'test.EntryPoint$Super.getX()I' via super "
+            + "(test/EntryPoint.java:9).");
+  }
+
+  public void testJsPropertyCallSucceeds()
+      throws UnableToCompleteException {
+    addSnippetImport("com.google.gwt.core.client.js.JsType");
+    addSnippetImport("com.google.gwt.core.client.js.JsProperty");
+    addSnippetClassDecl(
+        "@JsType public static class Super {",
+        "  @JsProperty public int getX() { return 5; }",
+        "}",
+        "@JsType public static class Buggy extends Super {",
+        "  public int m() { return getX(); }",
+        "}");
+
+    assertBuggySucceeds();
+  }
+
+  // TODO(rluble): this test should succeed, fix after eliminating the accidental overrides.
+  public void testJsPropertyAccidentalSuperCallFails()
+      throws UnableToCompleteException {
+    addSnippetImport("com.google.gwt.core.client.js.JsType");
+    addSnippetImport("com.google.gwt.core.client.js.JsProperty");
+    addSnippetClassDecl(
+        "@JsType public static class Super {",
+        "  @JsProperty public int getX() { return 5; }",
+        "}",
+        "@JsType public interface Interface {",
+        "  @JsProperty int getX();",
+        "}",
+
+        "@JsType public static class Buggy extends Super implements Interface {",
+        "}");
+
+    assertBuggyFails(
+        "Cannot call property accessor 'test.EntryPoint$Super.getX()I' via super "
+            + "(test/EntryPoint.java:6).");
+  }
+
   public void testMultiplePrivateConstructorsExportSucceeds() throws Exception {
     addSnippetImport("com.google.gwt.core.client.js.JsExport");
     addSnippetClassDecl(