Fixes SDM to incl. implementors of interfaces in stale types
Earlier implementors of interfaces were not included in
subtypes hence when an interface was changed, the callers
of implementors were not considered stale. However they
need to be consider stale and recompiled (due to defender
methods, JsInterop, etc.).
The patch also converts last piece of CompilerTest to run
with new jsinterop annotations.
Change-Id: I75296d7ee10251b2968a522547243a61d3a71bdc
Review-Link: https://gwt-review.googlesource.com/#/c/13792/
diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java
index 611d544..e8a0c03 100644
--- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java
+++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java
@@ -36,6 +36,7 @@
import com.google.gwt.thirdparty.guava.common.collect.HashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
+import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import com.google.gwt.thirdparty.guava.common.collect.Multimaps;
@@ -68,12 +69,7 @@
private static void appendSubTypes(Set<String> accumulatedTypeNames, Set<String> parentTypeNames,
JTypeOracle typeOracle) {
for (String parentTypeName : parentTypeNames) {
- Set<String> subTypeNames = typeOracle.getSubTypeNames(parentTypeName);
- if (subTypeNames == null) {
- // It must be a new type, thus there are no subtypes to invalidate.
- continue;
- }
- accumulatedTypeNames.addAll(subTypeNames);
+ Iterables.addAll(accumulatedTypeNames, typeOracle.getSubTypeNames(parentTypeName));
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index 309b911..d710edc 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -998,7 +998,7 @@
}
public Collection<JType> getSubclasses(JType type) {
- return Collections2.transform(typeOracle.getSubTypeNames(type.getName()),
+ return Collections2.transform(typeOracle.getSubClassNames(type.getName()),
new Function<String, JType>() {
@Override
public JType apply(String typeName) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
index 37610ab..c83fc04 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
@@ -860,9 +860,17 @@
return subclassesByClass.containsEntry(type.getName(), possibleSubType.getName());
}
- public Set<String> getSubTypeNames(String typeName) {
- return Sets.union((Set<String>) subclassesByClass.get(typeName),
- (Set<String>) subInterfacesByInterface.get(typeName));
+ public Iterable<String> getSubTypeNames(String typeName) {
+ return Iterables.concat(classesByImplementingInterface.get(typeName),
+ subclassesByClass.get(typeName), subInterfacesByInterface.get(typeName));
+ }
+
+ public Set<String> getSubClassNames(String typeName) {
+ return (Set<String>) subclassesByClass.get(typeName);
+ }
+
+ public Set<String> getSubInterfaceNames(String typeName) {
+ return (Set<String>) subInterfacesByInterface.get(typeName);
}
/**
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 4b445c2..d2461b7 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
@@ -417,7 +417,7 @@
logError("'%s' cannot be both a JsFunction and a JsType at the same time.", type);
}
- Set<String> subTypes = jprogram.typeOracle.getSubTypeNames(type.getName());
+ Set<String> subTypes = jprogram.typeOracle.getSubInterfaceNames(type.getName());
if (!subTypes.isEmpty()) {
logError("JsFunction '%s' cannot be extended by other interfaces:%s", type, subTypes);
}
@@ -437,7 +437,7 @@
logError("JsFunction implementation '%s' cannot extend a class.", type);
}
- Set<String> subTypes = jprogram.typeOracle.getSubTypeNames(type.getName());
+ Set<String> subTypes = jprogram.typeOracle.getSubClassNames(type.getName());
if (!subTypes.isEmpty()) {
logError("Implementation of JsFunction '%s' cannot be extended by other classes:%s", type,
subTypes);
diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java
index 4fb2ea0..afc68b4 100644
--- a/dev/core/test/com/google/gwt/dev/CompilerTest.java
+++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java
@@ -455,9 +455,8 @@
JavaResourceBase.createMockJavaResource(
"com.foo.Bar",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsType;",
- "@JsType @JsExport public class Bar {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public class Bar {",
" void doInstanceBar() {}",
" public static void doStaticBaz() {}",
"}");
@@ -481,6 +480,16 @@
" public void onModuleLoad() {}",
"}");
+ MockJavaResource entryPointResourceForFoo =
+ JavaResourceBase.createMockJavaResource("com.foo.TestEntryPoint",
+ "package com.foo;",
+ "import com.google.gwt.core.client.EntryPoint;",
+ "import com.foo.Foo;",
+ "public class TestEntryPoint implements EntryPoint {",
+ " @Override",
+ " public void onModuleLoad() { new Foo(); }",
+ "}");
+
private MockJavaResource gwtCreateEntryPointResource =
JavaResourceBase.createMockJavaResource("com.foo.TestEntryPoint",
"package com.foo;",
@@ -957,7 +966,6 @@
*/
public void testGwtCreateJsTypeRebindResult() throws Exception {
CompilerOptions compilerOptions = new CompilerOptionsImpl();
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS_RC);
compileToJs(compilerOptions, Files.createTempDir(), "com.foo.SimpleModule",
Lists.newArrayList(simpleModuleResource, gwtCreateEntryPointResource),
new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED);
@@ -1014,7 +1022,6 @@
"</module>");
CompilerOptions compilerOptions = new CompilerOptionsImpl();
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS_RC);
String js = compileToJs(compilerOptions, Files.createTempDir(), testEntryPoint.getTypeName(),
Lists.newArrayList(moduleResource, testEntryPoint, someJsFunction,
jsFunctionInterfaceImplementation, someInterface),
@@ -1028,7 +1035,7 @@
}
/**
- * Tests that changing @JsNamespace name on an exported method comes out accurately.
+ * Tests that changing Js namespace name on an exported method comes out accurately.
*
* <p>An unrelated and non-updated @JsType is also included in each compile to verify that updated
* exports do not forget non-edited items in a recompile.
@@ -1036,26 +1043,23 @@
public void testChangeJsNamespaceOnMethod() throws Exception {
CompilerOptions compilerOptions = new CompilerOptionsImpl();
compilerOptions.setUseDetailedTypeIds(true);
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS);
MockJavaResource jsNamespaceFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsNamespace;",
- "import com.google.gwt.core.client.js.JsType;",
- "@JsExport public class Foo {",
- " @JsNamespace(\"spazz\") public static void doStaticBar() {}",
+ "import jsinterop.annotations.JsMethod;",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public class Foo {",
+ " @JsMethod(namespace=\"spazz\") public static void doStaticBar() {}",
"}");
MockJavaResource regularFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsType;",
- "@JsExport public class Foo {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public class Foo {",
" public static void doStaticBar() {}",
"}");
@@ -1070,7 +1074,7 @@
}
/**
- * Tests that changing @JsNamespace name on a class comes out accurately.
+ * Tests that changing Js namespace on a class comes out accurately.
*
* <p>An unrelated and non-updated @JsType is also included in each compile to verify that updated
* exports do not forget non-edited items in a recompile.
@@ -1078,16 +1082,13 @@
public void testChangeJsNamespaceOnClass() throws Exception {
CompilerOptions compilerOptions = new CompilerOptionsImpl();
compilerOptions.setUseDetailedTypeIds(true);
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS);
MockJavaResource jsNamespaceFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsNamespace;",
- "import com.google.gwt.core.client.js.JsType;",
- "@JsNamespace(\"spazz\") @JsExport public class Foo {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType(namespace=\"spazz\") public class Foo {",
" public static void doStaticBar() {}",
"}");
@@ -1095,9 +1096,8 @@
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsType;",
- "@JsExport public class Foo {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public class Foo {",
" public static void doStaticBar() {}",
"}");
@@ -1120,13 +1120,12 @@
public void testChangeJsFunction() throws Exception {
CompilerOptions compilerOptions = new CompilerOptionsImpl();
compilerOptions.setUseDetailedTypeIds(true);
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS);
MockJavaResource jsFunctionIFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.IFoo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsFunction;",
+ "import jsinterop.annotations.JsFunction;",
"@JsFunction public interface IFoo {",
" int foo(int x);",
"}");
@@ -1143,8 +1142,7 @@
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "@JsExport public class Foo implements IFoo {",
+ "public class Foo implements IFoo {",
" @Override public int foo(int x) { return 0; }",
"}");
@@ -1152,10 +1150,10 @@
compilerOptions,
"com.foo.SimpleModule",
Lists.newArrayList(
- simpleModuleResource, emptyEntryPointResource, fooResource, jsTypeBarResource),
+ simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource),
regularIFooResource,
jsFunctionIFooResource,
- stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo"),
+ stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"),
JsOutputOption.DETAILED);
}
@@ -1168,14 +1166,13 @@
public void testChangeJsProperty() throws Exception {
CompilerOptions compilerOptions = new CompilerOptionsImpl();
compilerOptions.setUseDetailedTypeIds(true);
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS);
MockJavaResource jsPropertyIFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.IFoo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsProperty;",
- "import com.google.gwt.core.client.js.JsType;",
+ "import jsinterop.annotations.JsProperty;",
+ "import jsinterop.annotations.JsType;",
"@JsType public interface IFoo {",
" @JsProperty int getX();",
" @JsProperty int getY();",
@@ -1185,7 +1182,7 @@
JavaResourceBase.createMockJavaResource(
"com.foo.IFoo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsType;",
+ "import jsinterop.annotations.JsType;",
"@JsType public interface IFoo {",
" int getX();",
" int getY();",
@@ -1195,8 +1192,7 @@
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "@JsExport public class Foo implements IFoo {",
+ "public class Foo implements IFoo {",
" @Override public int getX() { return 0; }",
" @Override public int getY() { return 0; }",
"}");
@@ -1205,10 +1201,10 @@
compilerOptions,
"com.foo.SimpleModule",
Lists.newArrayList(
- simpleModuleResource, emptyEntryPointResource, fooResource, jsTypeBarResource),
+ simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource),
regularIFooResource,
jsPropertyIFooResource,
- stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo"),
+ stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"),
JsOutputOption.DETAILED);
}
@@ -1222,15 +1218,13 @@
public void testChangeJsType() throws Exception {
CompilerOptions compilerOptions = new CompilerOptionsImpl();
compilerOptions.setUseDetailedTypeIds(true);
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS);
MockJavaResource jsTypeFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsType;",
- "@JsType @JsExport public class Foo {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public class Foo {",
" void doInstanceBar() {}",
" public static void doStaticBar() {}",
"}");
@@ -1255,18 +1249,16 @@
* <p>An unrelated and non-updated @JsType is also included in each compile to verify that updated
* exports do not forget non-edited items in a recompile.
*/
- public void testChangeJsTypePrototype() throws Exception {
+ public void testChangeJsTypeNative() throws Exception {
CompilerOptions compilerOptions = new CompilerOptionsImpl();
compilerOptions.setUseDetailedTypeIds(true);
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS);
- MockJavaResource prototypeFooResource =
+ MockJavaResource nativeFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsType;",
- "@JsType(prototype = \"window.Date\") @JsExport public class Foo {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType(isNative=true) public class Foo {",
" public static void doStaticBar() {}",
"}");
@@ -1274,9 +1266,8 @@
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsType;",
- "@JsType @JsExport public class Foo {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public class Foo {",
" public static void doStaticBar() {}",
"}");
@@ -1285,39 +1276,38 @@
"com.foo.SimpleModule",
Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource),
regularFooResource,
- prototypeFooResource,
+ nativeFooResource,
stringSet("com.foo.Bar", "com.foo.Foo"),
JsOutputOption.DETAILED);
}
/**
- * Tests that adding a @JsNoExport annotation on a method comes out accurately and that removing
+ * Tests that adding a @JsIgnore annotation on a method comes out accurately and that removing
* it comes out accurately as well.
*
* <p>An unrelated and non-updated @JsType is also included in each compile to verify that updated
* exports do not forget non-edited items in a recompile.
*/
- public void testChangeJsNoExport() throws Exception {
+ public void testChangeJsIgnore() throws Exception {
CompilerOptions compilerOptions = new CompilerOptionsImpl();
compilerOptions.setUseDetailedTypeIds(true);
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS);
- MockJavaResource jsNoExportFooResource =
+ MockJavaResource jsIgnoreFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "import com.google.gwt.core.client.js.JsNoExport;",
- "@JsExport public class Foo {",
- " @JsNoExport public static void doStaticBar() {}",
+ "import jsinterop.annotations.JsIgnore;",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public class Foo {",
+ " @JsIgnore public static void doStaticBar() {}",
"}");
MockJavaResource regularFooResource =
JavaResourceBase.createMockJavaResource(
"com.foo.Foo",
"package com.foo;",
- "import com.google.gwt.core.client.js.JsExport;",
- "@JsExport public class Foo {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public class Foo {",
" public static void doStaticBar() {}",
"}");
@@ -1326,7 +1316,7 @@
"com.foo.SimpleModule",
Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource),
regularFooResource,
- jsNoExportFooResource,
+ jsIgnoreFooResource,
stringSet("com.foo.Bar", "com.foo.Foo"),
JsOutputOption.DETAILED);
}
@@ -1335,7 +1325,6 @@
MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache();
File applicationDir = Files.createTempDir();
CompilerOptions compilerOptions = new CompilerOptionsImpl();
- compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS_RC);
// Simple compile with one dialog.alert() export succeeds.
compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", Lists.newArrayList(
@@ -1981,7 +1970,8 @@
checkRecompiledModifiedApp("com.foo.SuperFromStaleInnerModule",
Lists.newArrayList(superFromStaleInnerModuleResource,
superFromStaleInnerEntryPointResource), interfaceOneResource, interfaceOneResource,
- stringSet(interfaceOneResource.getTypeName(), "com.foo.SuperFromStaleInnerEntryPoint$B$1"),
+ stringSet(interfaceOneResource.getTypeName(), "com.foo.SuperFromStaleInnerEntryPoint$B",
+ "com.foo.SuperFromStaleInnerEntryPoint$B$1"),
output);
}
@@ -2347,6 +2337,7 @@
// Setup options to perform a per-file compile, output to this new application directory and
// compile the given module.
compilerOptions.setIncrementalCompileEnabled(true);
+ compilerOptions.setJsInteropMode(OptionJsInteropMode.Mode.JS_RC);
compilerOptions.setWarDir(applicationDir);
compilerOptions.setModuleNames(ImmutableList.of(moduleName));
compilerOptions.setOutput(output);