Revision: 10313
Author:   [email protected]
Date:     Fri Jun 10 05:39:40 2011
Log:      ForeachStatement fix for GwtAstBuilder.

Fixes a compile error that occurs with code like this:

interface SubIterator<E> extends Iterator<E> {
}

class Foo implements Iterable<String> {
@Override
public SubIterator<String> iterator() {
return null;
}
}

We were trying to find 'SubIterator.next()' which isn't modeled in JDT. It turns out JDT has the right answer in a private field.

http://gwt-code-reviews.appspot.com/1450814/

Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=10313

Modified:
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
 /trunk/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java Thu Jun 9 11:46:19 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java Fri Jun 10 05:39:40 2011
@@ -199,6 +199,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
 import org.eclipse.jdt.internal.compiler.util.Util;

+import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -979,16 +980,7 @@
           // Perform any implicit reference type casts (due to generics).
           // Note this occurs before potential unboxing.
           if (elementVar.getType() != javaLangObject) {
-            /*
- * Compute the collection element type by walking the iterator()
-             * method, which may be parameterized.
-             */
- ReferenceBinding collectionType = (ReferenceBinding) x.collection.resolvedType;
-            MethodBinding iteratorMethod =
- collectionType.getExactMethod(ITERATOR, NO_TYPES, cudScope); - ReferenceBinding iteratorType = (ReferenceBinding) iteratorMethod.returnType;
-            MethodBinding nextMethod = iteratorType.getMethods(NEXT)[0];
-            TypeBinding collectionElementType = nextMethod.returnType;
+ TypeBinding collectionElementType = (TypeBinding) collectionElementTypeField.get(x);
             JType toType = typeMap.get(collectionElementType);
             assert (toType instanceof JReferenceType);
elementDecl.initializer = maybeCast(toType, elementDecl.initializer);
@@ -2762,6 +2754,12 @@

   private static final char[] _STRING = "_String".toCharArray();
   private static final String ARRAY_LENGTH_FIELD = "length";
+
+  /**
+   * Reflective access to {@link ForeachStatement#collectionElementType}.
+   */
+  private static final Field collectionElementTypeField;
+
private static final char[] CREATE_VALUE_OF_MAP = "createValueOfMap".toCharArray();
   private static final char[] HAS_NEXT = "hasNext".toCharArray();
   private static final char[] ITERATOR = "iterator".toCharArray();
@@ -2775,6 +2773,13 @@

   static {
     InternalCompilerException.preload();
+    try {
+ collectionElementTypeField = ForeachStatement.class.getDeclaredField("collectionElementType");
+      collectionElementTypeField.setAccessible(true);
+    } catch (Exception e) {
+      throw new RuntimeException(
+ "Unexpectedly unable to access ForeachStatement.collectionElementType via reflection", e);
+    }
   }

   static String dotify(char[][] name) {
=======================================
--- /trunk/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java Mon Apr 19 09:23:34 2010 +++ /trunk/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java Fri Jun 10 05:39:40 2011
@@ -17,6 +17,9 @@

 import com.google.gwt.junit.client.GWTTestCase;

+import java.util.Arrays;
+import java.util.Iterator;
+
 /**
  * This test is intended to exercise as many code paths and node types as
* possible in the Java to JavaScript compiler. This test is not at all intended
@@ -412,9 +415,66 @@
     }

     private void testForeachStatement() {
+      // Array of primitive.
       for (int q : ia) {
         i = q;
       }
+      // Array of primitive with unboxing.
+      for (Integer q : ia) {
+        i = q;
+      }
+      // Array of object.
+      for (String str : sa) {
+        s = str;
+      }
+      // Iterable.
+      for (Object obj : Arrays.asList(new Object(), new Object())) {
+        o = obj;
+      }
+      // Iterable with unboxing.
+      for (int q : Arrays.asList(1, 2, 3)) {
+        i = q;
+      }
+      // Iterable with generic cast.
+      for (String str : Arrays.asList(sa)) {
+        s = str;
+      }
+      // Iterable with array element.
+      for (String[] stra : Arrays.asList(sa, sa, sa)) {
+        s = sa[0];
+      }
+      // Iterable Iterator subclass.
+      class SubIterator<T> implements Iterator<T> {
+        private final Iterator<T> it;
+
+        public SubIterator(Iterator<T> it) {
+          this.it = it;
+        }
+
+        @Override
+        public boolean hasNext() {
+          return it.hasNext();
+        }
+
+        @Override
+        public T next() {
+          return it.next();
+        }
+
+        @Override
+        public void remove() {
+          it.remove();
+        }
+      }
+      class SubIterableString implements Iterable<String> {
+        @Override
+        public SubIterator<String> iterator() {
+          return new SubIterator<String>(Arrays.asList(sa).iterator());
+        }
+      }
+      for (String str : new SubIterableString()) {
+        s = str;
+      }
     }

     private void testForStatement() {
@@ -751,6 +811,8 @@

   public static String s = "foo";

+  public static String[] sa = new String[]{"foo", "bar", "bar"};
+
   public static CoverageTest singleton;

   public static boolean z;

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

Reply via email to