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: jbrosenberg@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10313 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
index 7d0957b..50d98cb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
@@ -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) {
diff --git a/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java b/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java
index daebfc7..2ba5ddd 100644
--- a/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java
@@ -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;