Require JsFunction implementations be marked final.
The requirement does not affect current expressivity as there
is a restriction in place that JsFunction implementations can not
be subclassed.
Change-Id: I45ab86af287e746e4ad5d0c0a8fc8c508a52bc9c
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 021dd5c..063e6d7 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
@@ -688,6 +688,10 @@
}
private void checkJsFunctionImplementation(JDeclaredType type) {
+ if (!type.isFinal()) {
+ logError("JsFunction implementation '%s' must be final.",
+ type);
+ }
if (type.getImplements().size() != 1) {
logError("JsFunction implementation '%s' cannot implement more than one interface.",
type);
@@ -704,11 +708,6 @@
}
private void checkJsFunctionSubtype(JDeclaredType type) {
- JClassType superClass = type.getSuperClass();
- if (superClass != null && superClass.isJsFunctionImplementation()) {
- logError(type, "'%s' cannot extend JsFunction implementation '%s'.",
- JjsUtils.getReadableDescription(type), JjsUtils.getReadableDescription(superClass));
- }
for (JInterfaceType superInterface : type.getImplements()) {
if (superInterface.isJsFunction()) {
logError(type, "'%s' cannot extend JsFunction '%s'.",
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 3be61df..f76803b 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
@@ -1140,17 +1140,6 @@
assertBuggySucceeds();
}
- public void testJsFunctionWithNoExtendsSucceeds() throws Exception {
- addSnippetImport("jsinterop.annotations.JsFunction");
- addSnippetClassDecl(
- "@JsFunction",
- "public interface Buggy {",
- " void foo();",
- "}");
-
- assertBuggySucceeds();
- }
-
public void testJsFunctionExtendsInterfaceFails() throws Exception {
addSnippetImport("jsinterop.annotations.JsFunction");
addSnippetClassDecl(
@@ -1185,11 +1174,19 @@
"Line 6: 'EntryPoint.Buggy' cannot be both a JsFunction and a JsType at the same time.");
}
- public void testJsFunctionImplementationWithSingleInterfaceSucceeds() throws Exception {
- addAll(jsFunctionInterface);
+ public void testJsFunctionImplementationSucceeds() throws Exception {
+ addSnippetImport("jsinterop.annotations.JsFunction");
addSnippetClassDecl(
- "public static class Buggy implements MyJsFunctionInterface {",
- " public int foo(int x) { return 0; }",
+ "@JsFunction",
+ "public interface Function {",
+ " void foo();",
+ "}",
+ "public static final class Buggy implements Function {",
+ " public void foo() {",
+ " new Function() {",
+ " public void foo() {}",
+ " }.foo();",
+ " }",
"}");
assertBuggySucceeds();
@@ -1199,7 +1196,7 @@
addAll(jsFunctionInterface);
addSnippetClassDecl(
"interface AnotherInterface {}",
- "public static class Buggy implements MyJsFunctionInterface, AnotherInterface {",
+ "public static final class Buggy implements MyJsFunctionInterface, AnotherInterface {",
" public int foo(int x) { return 0; }",
" public int bar(int x) { return 0; }",
"}");
@@ -1212,7 +1209,7 @@
addAll(jsFunctionInterface);
addSnippetClassDecl(
"public static class BaseClass {}",
- "public static class Buggy extends BaseClass implements MyJsFunctionInterface {",
+ "public static final class Buggy extends BaseClass implements MyJsFunctionInterface {",
" public int foo(int x) { return 0; }",
"}");
@@ -1220,7 +1217,7 @@
+ "extend a class.");
}
- public void testJsFunctionImplementationWithSubclassesFails() throws Exception {
+ public void testJsFunctionImplementationNotFinalFails() throws Exception {
addAll(jsFunctionInterface);
addSnippetClassDecl(
"public static class BaseClass implements MyJsFunctionInterface {",
@@ -1229,8 +1226,7 @@
"public static class Buggy extends BaseClass {",
"}");
- assertBuggyFails("Line 6: 'EntryPoint.Buggy' cannot extend "
- + "JsFunction implementation 'EntryPoint.BaseClass'.");
+ assertBuggyFails("Line 3: JsFunction implementation 'EntryPoint.BaseClass' must be final.");
}
public void testJsFunctionImplementationMarkedAsJsTypeFails() throws Exception {
@@ -1238,7 +1234,7 @@
addSnippetImport("jsinterop.annotations.JsType");
addSnippetClassDecl(
"@JsType",
- "public static class Buggy implements MyJsFunctionInterface {",
+ "public static final class Buggy implements MyJsFunctionInterface {",
" public int foo(int x) { return 0; }",
"}");