Fix incorrect computation in JTypeOracle.computeSingleJsoImplData() which to include super-interfaces when determining if an interface is a tag interface.
Patch by: bobv
Review by: scottb
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5756 8db76d5a-ed1c-0410-87a9-c151d255dfc7
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 48272af..c431a96 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
@@ -488,6 +488,36 @@
}
/**
+ * Returns true if the given type and it's super-interfaces define no methods.
+ */
+ public boolean isTagInterface(JInterfaceType type) {
+ Set<JInterfaceType> seen = new IdentityHashSet<JInterfaceType>();
+ List<JInterfaceType> q = new LinkedList<JInterfaceType>();
+ seen.add(type);
+ q.add(type);
+
+ while (!q.isEmpty()) {
+ JInterfaceType intf = q.remove(0);
+
+ List<JMethod> methods = intf.getMethods();
+ int size = methods.size();
+ if (size == 0
+ || (size == 1 && methods.get(0).getName().equals("$clinit"))) {
+ // OK, add any super-interfaces;
+ for (JInterfaceType superIntf : intf.getImplements()) {
+ if (seen.add(superIntf)) {
+ q.add(superIntf);
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
* This method should be called after altering the types that are live in the
* associated JProgram.
*/
@@ -683,14 +713,12 @@
}
JInterfaceType intr = (JInterfaceType) refType;
- if (intr.getMethods().size() <= 1) {
+ if (isTagInterface(intr)) {
/*
* Record a tag interface as being implemented by JSO, since they
* don't actually have any methods and we want to avoid spurious
* messages about multiple JSO types implementing a common interface.
*/
- assert intr.getMethods().size() == 0
- || intr.getMethods().get(0).getName().equals("$clinit");
jsoSingleImpls.put(intr, program.getJavaScriptObject());
/*
diff --git a/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java b/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java
index f50be8b..b954f3e 100644
--- a/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.test.singlejso;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.junit.client.GWTTestCase;
/**
@@ -22,6 +23,42 @@
*/
public class TypeHierarchyTest extends GWTTestCase {
+ /**
+ * The bottom type for a non-trivial diamond-shaped inheritance pattern.
+ */
+ static class DiamondImpl extends JavaScriptObject implements IDiamond2A,
+ IDiamond2B {
+ public static native DiamondImpl create() /*-{
+ return {size : 42};
+ }-*/;
+
+ protected DiamondImpl() {
+ }
+
+ public final native int size() /*-{
+ return this.size;
+ }-*/;
+ }
+
+ /**
+ * The root type for a non-trivial diamond-shaped inheritance pattern.
+ */
+ interface IDiamond1 {
+ int size();
+ }
+
+ /**
+ * The left type for a non-trivial diamond-shaped inheritance pattern.
+ */
+ interface IDiamond2A extends IDiamond1 {
+ }
+
+ /**
+ * The right type for a non-trivial diamond-shaped inheritance pattern.
+ */
+ interface IDiamond2B extends IDiamond1 {
+ }
+
@Override
public String getModuleName() {
return "com.google.gwt.dev.jjs.CompilerSuite";
@@ -60,4 +97,14 @@
assertEquals("B2", b2.whoAmI());
}
+ public void testDiamond() {
+ IDiamond1 d1 = DiamondImpl.create();
+ assertEquals(42, d1.size());
+
+ IDiamond2A d2a = DiamondImpl.create();
+ assertEquals(42, d2a.size());
+
+ IDiamond2B d2b = DiamondImpl.create();
+ assertEquals(42, d2b.size());
+ }
}