Revision: 9542
Author: knor...@google.com
Date: Thu Jan 13 15:08:15 2011
Log: Fixes a bug in JavaScriptObject support in DevMode that prevents dispatching
through an interface to a method defined in a super-interface. The change
also includes a new test to serve as a regression test.

Review at http://gwt-code-reviews.appspot.com/1287801
Review by: bobv, scottb, cromwellian

http://code.google.com/p/google-web-toolkit/source/detail?r=9542

Modified:
/trunk/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java /trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java Wed Dec 1 12:10:45 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java Thu Jan 13 15:08:15 2011
@@ -34,8 +34,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import java.util.SortedSet;
+import java.util.TreeSet;

 /**
* Effects the renaming of {@code @SingleJsoImpl} methods from their original
@@ -181,9 +181,9 @@
      * may be referenced via a more specific interface.
      */
     if (inSingleJsoImplInterfaceType) {
- for (Map.Entry<String, List<Method>> entry : toImplement(currentTypeName).entrySet()) {
-        for (Method method : entry.getValue()) {
-          writeEmptyMethod(entry.getKey(), method);
+      for (String mangledName : toImplement(currentTypeName)) {
+        for (Method method : jsoData.getDeclarations(mangledName)) {
+          writeEmptyMethod(mangledName, method);
         }
       }
     }
@@ -265,29 +265,23 @@
* Given a resource name of a class, find all mangled method names that must
    * be implemented.
    */
-  private SortedMap<String, List<Method>> toImplement(String typeName) {
+  private SortedSet<String> toImplement(String typeName) {
     String name = typeName.replace('/', '_');
     String prefix = name + "_";
     String suffix = name + "`";
- SortedMap<String, List<Method>> toReturn = new TreeMap<String, List<Method>>();
-
+    SortedSet<String> toReturn = new TreeSet<String>();
for (String mangledName : jsoData.getMangledNames().subSet(prefix, suffix)) {
-      toReturn.put(mangledName, jsoData.getImplementations(mangledName));
-    }
-    toReturn.keySet().removeAll(implementedMethods);
+      if (!implementedMethods.contains(mangledName)) {
+        toReturn.add(mangledName);
+      }
+    }
     return toReturn;
   }
-
-  private void writeEmptyMethod(String mangledMethodName, Method method) {
-    assert method.getArgumentTypes().length > 0;
-    // Remove the first argument, which would be the implementing JSO type
-    String descriptor = "("
-        + method.getDescriptor().substring(
-            1 + method.getArgumentTypes()[0].getDescriptor().length());
-
-    // Create the stub method entry in the interface
+
+ private void writeEmptyMethod(String mangledMethodName, Method declMethod) {
     MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC
-        | Opcodes.ACC_ABSTRACT, mangledMethodName, descriptor, null, null);
+ | Opcodes.ACC_ABSTRACT, mangledMethodName, declMethod.getDescriptor(),
+        null, null);
     mv.visitEnd();
   }

@@ -303,20 +297,14 @@
* semantics of the dispatches that would make a common implementation far
      * more awkward than the duplication of code.
      */
- for (Map.Entry<String, List<Method>> entry : toImplement(stubIntr).entrySet()) {
-      for (Method method : entry.getValue()) {
-        String mangledName = entry.getKey();
-
-        String descriptor = "("
-            + method.getDescriptor().substring(
-                1 + method.getArgumentTypes()[0].getDescriptor().length());
-        String localName = method.getName().substring(0,
-            method.getName().length() - 1);
-        Method toCall = new Method(localName, descriptor);
+    for (String mangledName : toImplement(stubIntr)) {
+      for (Method method : jsoData.getDeclarations(mangledName)) {
+
+ Method toCall = new Method(method.getName(), method.getDescriptor());

         // Must not be final
         MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC
-            | Opcodes.ACC_SYNTHETIC, mangledName, descriptor, null, null);
+ | Opcodes.ACC_SYNTHETIC, mangledName, method.getDescriptor(), null, null);
         if (mv != null) {
           mv.visitCode();

=======================================
--- /trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java Sun Oct 18 11:48:45 2009 +++ /trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java Thu Jan 13 15:08:15 2011
@@ -122,6 +122,45 @@
    */
   static class Wide {
   }
+
+  private interface Element extends Node {
+  }
+
+  private static class JvmNode implements Node {
+    @Override
+    public JvmNode appendChild(Node node) {
+      return (JvmNode)node;
+    }
+  }
+
+ private final static class JvmElement extends JvmNode implements Element {
+    static Element create() {
+      return new JvmElement();
+    }
+  }
+
+  private final static class JsElement extends JsNode implements Element {
+    static Element create() {
+      return (Element) JavaScriptObject.createObject();
+    }
+
+    protected JsElement() {
+    }
+  }
+
+  private static class JsNode extends JavaScriptObject implements Node {
+    @Override
+    public final native JsNode appendChild(Node node) /*-{
+      return node;
+    }-*/;
+
+    protected JsNode() {
+    }
+  }
+
+  private interface Node {
+    Node appendChild(Node node);
+  }

   @Override
   public String getModuleName() {
@@ -149,7 +188,7 @@
     IA b2 = new B2();
     assertEquals("B2", b2.whoAmI());
   }
-
+
   public void testCase3() {
     IA a = A.create();
     assertEquals("A", a.whoAmI());
@@ -171,6 +210,17 @@
     IDiamond2B d2b = DiamondImpl.create();
     assertEquals(42, d2b.size());
   }
+
+  /**
+ * Tests that dispatches through a hierarchy of interfaces works properly.
+   */
+  public void testInterfaceHierarchyDispatch() {
+    Element jsElement = JsElement.create();
+    assertEquals(jsElement, jsElement.appendChild(jsElement));
+
+    Element jvmElement = JvmElement.create();
+    assertEquals(jvmElement, jvmElement.appendChild(jvmElement));
+  }

   public void testVirtualOverrides() {
     Arrayish array = PlainJsoWithInterface.create();

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to