Allow arbitrary clinit code in native JsTypes and JsFunction interfaces.
Since clinit on these types are effectively overlays there is
no need to have any restrictions on them.
Change-Id: If0aba24ce6b1a4732461c755f0731ee687cfb01d
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 2e070c2..7c1dbb8 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
@@ -25,7 +25,6 @@
import com.google.gwt.dev.jjs.ast.HasType;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConstructor;
-import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JDeclaredType.NestedClassDisposition;
import com.google.gwt.dev.jjs.ast.JExpression;
@@ -135,46 +134,6 @@
|| ((JMethodBody) type.getInitMethod().getBody()).getStatements().isEmpty();
}
- /**
- * Returns true if the clinit for a type is locally empty (except for the call to its super
- * clinit).
- */
- private static boolean isClinitEmpty(JDeclaredType type, final boolean skipDeclaration) {
- JMethod clinit = type.getClinitMethod();
- List<JStatement> statements = FluentIterable
- .from(((JMethodBody) clinit.getBody()).getStatements())
- .filter(new Predicate<JStatement>() {
- @Override
- public boolean apply(JStatement statement) {
- if (!(statement instanceof JDeclarationStatement)) {
- return true;
- }
- if (skipDeclaration) {
- return false;
- }
- JDeclarationStatement declarationStatement = (JDeclarationStatement) statement;
- JField field = (JField) declarationStatement.getVariableRef().getTarget();
- return !field.isCompileTimeConstant();
- }
- }).toList();
- if (statements.isEmpty()) {
- return true;
- }
- return statements.size() == 1 && isClinitCall(statements.get(0), type.getSuperClass());
- }
-
- private static boolean isClinitCall(JStatement statement, JClassType superClass) {
- if (superClass == null || !(statement instanceof JExpressionStatement)) {
- return false;
- }
-
- JExpression expression = ((JExpressionStatement) statement).getExpr();
- if (!(expression instanceof JMethodCall)) {
- return false;
- }
- return ((JMethodCall) expression).getTarget() == superClass.getClinitMethod();
- }
-
private void checkJsConstructors(JDeclaredType x) {
List<JMethod> jsConstructors = FluentIterable
.from(x.getMethods())
@@ -671,10 +630,6 @@
logError("Native JsType '%s' cannot have initializer.", type);
}
- if (!isClinitEmpty(type, true)) {
- logError("Native JsType '%s' cannot have static initializer.", type);
- }
-
return true;
}
@@ -699,10 +654,6 @@
}
private void checkJsFunction(JDeclaredType type) {
- if (!isClinitEmpty(type, false)) {
- logError("JsFunction '%s' cannot have static initializer.", type);
- }
-
if (type.getImplements().size() > 0) {
logError("JsFunction '%s' cannot extend other interfaces.", 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 a110ab3..10f0325 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
@@ -1148,6 +1148,8 @@
"public interface Function {",
" int getFoo();",
" @JsOverlay",
+ " String s = someString();",
+ " @JsOverlay",
" default void m() {}",
" @JsOverlay",
" static void n() {}",
@@ -1199,8 +1201,6 @@
" default void m() {}",
" int f = 0;",
" static void n() {}",
- " @JsOverlay",
- " String s = null;",
"}",
"static class NonFinalJsFunction implements Function {",
" public int getFoo() { return 0; }",
@@ -1258,7 +1258,7 @@
+ "implement more than one interface.");
}
- public void testNativeJsTypeStaticInitializerFails() {
+ public void testNativeJsTypeStaticInitializerSucceeds() throws Exception {
addSnippetImport("jsinterop.annotations.JsType");
addSnippetClassDecl(
"@JsType(isNative=true) public static class Buggy {",
@@ -1268,9 +1268,7 @@
" static { Object.class.getName(); }",
"}");
- assertBuggyFails(
- "Line 4: Native JsType 'EntryPoint.Buggy' cannot have static initializer.",
- "Line 7: Native JsType 'EntryPoint.Buggy2' cannot have static initializer.");
+ assertBuggySucceeds();
}
public void testNativeJsTypeInstanceInitializerFails() {
diff --git a/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java b/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
index 367d65b..2dc6762 100644
--- a/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
+++ b/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
@@ -208,14 +208,22 @@
public final Object getObject() {
return object;
}
+
+ static {
+ clinitCalled++;
+ }
}
+ private static int clinitCalled = 0;
+
public void testNativeJsTypeWithStaticIntializer() {
assertEquals(new Integer(3), NativeJsTypeWithStaticInitializationAndFieldAccess.object);
+ assertEquals(0, clinitCalled);
assertEquals(
new Integer(4), NativeJsTypeWithStaticInitializationAndStaticOverlayMethod.getObject());
assertEquals(new Integer(5),
new NativeJsTypeWithStaticInitializationAndInstanceOverlayMethod().getObject());
+ assertEquals(1, clinitCalled);
}
@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Function")