Add native JsType checks to JsInteropRestriction checker.
Change-Id: I13a996af4353a5d02af9a311aefce5dd71f988fa
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 f6a7822..85f4c84 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
@@ -499,8 +499,6 @@
}
private boolean checkNativeJsType(JDeclaredType type) {
- // TODO(rluble): add inheritance restrictions.
-
if (type.isEnumOrSubclass() != null) {
logError("Enum '%s' cannot be a native JsType.", type);
return false;
@@ -511,6 +509,20 @@
return false;
}
+ JClassType superClass = type.getSuperClass();
+ if (superClass != null && superClass != jprogram.getTypeJavaLangObject() &&
+ !superClass.isJsNative()) {
+ logError("Native JsType '%s' can only extend native JsType classes.", type);
+ }
+
+ for (JInterfaceType interfaceType : type.getImplements()) {
+ if (!interfaceType.isJsNative()) {
+ logError(type, "Native JsType '%s' can only %s native JsType interfaces.",
+ getDescription(type),
+ type instanceof JInterfaceType ? "extend" : "implement");
+ }
+ }
+
if (!isClinitEmpty(type)) {
logError("Native JsType '%s' cannot have static initializer.", 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 139f50a..5b17008 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
@@ -1280,6 +1280,66 @@
assertBuggySucceeds();
}
+ public void testNativeJsTypeExtendsJsTypeFails() {
+ addSnippetImport("jsinterop.annotations.JsType");
+ addSnippetClassDecl(
+ "@JsType public static class Super {",
+ "}",
+ "@JsType(isNative=true) public static class Buggy extends Super {",
+ "}");
+
+ assertBuggyFails(
+ "Line 6: Native JsType 'EntryPoint.Buggy' can only extend native JsType classes.");
+ }
+
+ public void testNativeJsTypeImplementsJsTypeInterfaceFails() {
+ addSnippetImport("jsinterop.annotations.JsType");
+ addSnippetClassDecl(
+ "@JsType public interface Interface {",
+ "}",
+ "@JsType(isNative=true) public static class Buggy implements Interface {",
+ "}");
+
+ assertBuggyFails(
+ "Line 6: Native JsType ''EntryPoint.Buggy'' can only implement native JsType interfaces.");
+ }
+
+ public void testNativeJsTypeInterfaceExtendsJsTypeInterfaceFails() {
+ addSnippetImport("jsinterop.annotations.JsType");
+ addSnippetClassDecl(
+ "@JsType public interface Interface {",
+ "}",
+ "@JsType(isNative=true) public interface Buggy extends Interface {",
+ "}");
+
+ assertBuggyFails(
+ "Line 6: Native JsType ''EntryPoint.Buggy'' can only extend native JsType interfaces.");
+ }
+
+ public void testNativeJsTypeImplementsNonJsTypeFails() {
+ addSnippetImport("jsinterop.annotations.JsType");
+ addSnippetClassDecl(
+ "public interface Super {",
+ "}",
+ "@JsType(isNative=true) public static class Buggy implements Super {",
+ "}");
+
+ assertBuggyFails(
+ "Line 6: Native JsType ''EntryPoint.Buggy'' can only implement native JsType interfaces.");
+ }
+
+ public void testNativeJsTypeInterfaceExtendsNonJsTypeFails() {
+ addSnippetImport("jsinterop.annotations.JsType");
+ addSnippetClassDecl(
+ "public interface Super {",
+ "}",
+ "@JsType(isNative=true) public interface Buggy extends Super {",
+ "}");
+
+ assertBuggyFails(
+ "Line 6: Native JsType ''EntryPoint.Buggy'' can only extend native JsType interfaces.");
+ }
+
public void testJsOverlayOnNativeJsTypeMemberSucceeds() throws Exception {
addSnippetImport("jsinterop.annotations.JsType");
addSnippetImport("jsinterop.annotations.JsOverlay");