Fixes a ClassCircularityError that could be triggered computing the super interface hierarchy via class objects.
The new implementation uses TypeOracle.
Patch by: bobv
Review by: me
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5472 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java b/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
index 2e99313..2db2593 100644
--- a/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
+++ b/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
@@ -993,8 +993,8 @@
if (unit != null) {
anonymousClassMap = unit.getAnonymousClassMap();
}
- byte[] newBytes = classRewriter.rewrite(this, className, classBytes,
- anonymousClassMap);
+ byte[] newBytes = classRewriter.rewrite(typeOracle, className,
+ classBytes, anonymousClassMap);
if (CLASS_DUMP) {
if (!Arrays.equals(classBytes, newBytes)) {
classDump(className, newBytes);
diff --git a/dev/core/src/com/google/gwt/dev/shell/rewrite/HostedModeClassRewriter.java b/dev/core/src/com/google/gwt/dev/shell/rewrite/HostedModeClassRewriter.java
index 6f1621a..03c32d5 100644
--- a/dev/core/src/com/google/gwt/dev/shell/rewrite/HostedModeClassRewriter.java
+++ b/dev/core/src/com/google/gwt/dev/shell/rewrite/HostedModeClassRewriter.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.shell.rewrite;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.asm.ClassReader;
import com.google.gwt.dev.asm.ClassVisitor;
import com.google.gwt.dev.asm.ClassWriter;
@@ -183,14 +184,14 @@
/**
* Performs rewriting transformations on a class.
*
- * @param ccl the ClassLoader requesting the rewrite
+ * @param typeOracle a typeOracle modeling the user classes
* @param className the name of the class
* @param classBytes the bytes of the class
* @param anonymousClassMap a map between the anonymous class names of java
* compiler used to compile code and jdt. Emma-specific.
*/
- public byte[] rewrite(ClassLoader ccl, String className, byte[] classBytes,
- Map<String, String> anonymousClassMap) {
+ public byte[] rewrite(TypeOracle typeOracle, String className,
+ byte[] classBytes, Map<String, String> anonymousClassMap) {
String desc = toDescriptor(className);
assert (!jsoIntfDescs.contains(desc));
@@ -201,7 +202,7 @@
// v = new CheckClassAdapter(v);
// v = new TraceClassVisitor(v, new PrintWriter(System.out));
- v = new RewriteSingleJsoImplDispatches(v, ccl, singleJsoImplTypes,
+ v = new RewriteSingleJsoImplDispatches(v, typeOracle, singleJsoImplTypes,
mangledNamesToImplementations);
v = new RewriteRefsToJsoClasses(v, jsoIntfDescs, mapper);
diff --git a/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java b/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java
index 94bb354..00bdca1 100644
--- a/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java
+++ b/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java
@@ -15,6 +15,8 @@
*/
package com.google.gwt.dev.shell.rewrite;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.asm.ClassAdapter;
import com.google.gwt.dev.asm.ClassVisitor;
import com.google.gwt.dev.asm.MethodAdapter;
@@ -22,6 +24,8 @@
import com.google.gwt.dev.asm.Opcodes;
import com.google.gwt.dev.asm.Type;
import com.google.gwt.dev.asm.commons.Method;
+import com.google.gwt.dev.util.collect.Maps;
+import com.google.gwt.dev.util.collect.Sets;
import java.util.Collections;
import java.util.HashSet;
@@ -121,17 +125,17 @@
private String currentTypeName;
private final Set<String> implementedMethods = new HashSet<String>();
+ private boolean inSingleJsoImplInterfaceType;
+ private Map<String, Set<String>> intfNamesToAllInterfaces = Maps.create();
private final SortedMap<String, Method> mangledNamesToImplementations;
private final Set<String> singleJsoImplTypes;
- private boolean inSingleJsoImplInterfaceType;
+ private final TypeOracle typeOracle;
- private final ClassLoader ccl;
-
- public RewriteSingleJsoImplDispatches(ClassVisitor v, ClassLoader ccl,
+ public RewriteSingleJsoImplDispatches(ClassVisitor v, TypeOracle typeOracle,
Set<String> singleJsoImplTypes,
SortedMap<String, Method> mangledNamesToImplementations) {
super(v);
- this.ccl = ccl;
+ this.typeOracle = typeOracle;
this.singleJsoImplTypes = Collections.unmodifiableSet(singleJsoImplTypes);
this.mangledNamesToImplementations = Collections.unmodifiableSortedMap(mangledNamesToImplementations);
}
@@ -206,29 +210,49 @@
return new MyMethodVisitor(mv);
}
- private Set<String> computeAllInterfaces(String... interfaces) {
- Set<String> toReturn = new HashSet<String>();
- List<String> q = new LinkedList<String>();
- Collections.addAll(q, interfaces);
+ private Set<String> computeAllInterfaces(String intfName) {
+ Set<String> toReturn = intfNamesToAllInterfaces.get(intfName);
+ if (toReturn != null) {
+ return toReturn;
+ }
+
+ toReturn = Sets.create();
+ List<JClassType> q = new LinkedList<JClassType>();
+ JClassType intf = typeOracle.findType(intfName.replace('/', '.').replace(
+ '$', '.'));
+ assert intf != null : "Could not find interface " + intfName;
+ q.add(intf);
while (!q.isEmpty()) {
- String intf = q.remove(0);
- if (toReturn.add(intf)) {
- try {
- Class<?> intfClass = Class.forName(intf.replace('/', '.'), false, ccl);
- for (Class<?> i : intfClass.getInterfaces()) {
- q.add(i.getName().replace('.', '/'));
- }
- } catch (ClassNotFoundException e) {
- assert false : intf;
- e.printStackTrace();
- }
+ intf = q.remove(0);
+ String resourceName = getResourceName(intf);
+ if (!toReturn.contains(resourceName)) {
+ toReturn = Sets.add(toReturn, resourceName);
+ Collections.addAll(q, intf.getImplementedInterfaces());
}
}
+ intfNamesToAllInterfaces = Maps.put(intfNamesToAllInterfaces, intfName,
+ toReturn);
return toReturn;
}
+ private Set<String> computeAllInterfaces(String[] interfaces) {
+ Set<String> toReturn = new HashSet<String>();
+ for (String intfName : interfaces) {
+ toReturn.addAll(computeAllInterfaces(intfName));
+ }
+ return toReturn;
+ }
+
+ private String getResourceName(JClassType type) {
+ if (type.getEnclosingType() != null) {
+ return getResourceName(type.getEnclosingType()) + "$"
+ + type.getSimpleSourceName();
+ }
+ return type.getQualifiedSourceName().replace('.', '/');
+ }
+
/**
* Given a resource name of a class, find all mangled method names that must
* be implemented.