Author: [email protected]
Date: Thu Mar 19 17:28:46 2009
New Revision: 5058
Modified:
changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
Log:
Got generic parameters on methods (including those needed for local
classes) working.
Modified:
changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
==============================================================================
---
changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
(original)
+++
changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
Thu Mar 19 17:28:46 2009
@@ -40,6 +40,7 @@
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.asm.AnnotationVisitor;
import com.google.gwt.dev.asm.ClassReader;
+import com.google.gwt.dev.asm.ClassVisitor;
import com.google.gwt.dev.asm.FieldVisitor;
import com.google.gwt.dev.asm.Label;
import com.google.gwt.dev.asm.MethodVisitor;
@@ -48,6 +49,7 @@
import com.google.gwt.dev.asm.commons.EmptyVisitor;
import com.google.gwt.dev.asm.signature.SignatureReader;
import com.google.gwt.dev.asm.signature.SignatureVisitor;
+import com.google.gwt.dev.asm.util.TraceClassVisitor;
import
com.google.gwt.dev.javac.TypeOracleMediator.MyClassVisitor.AnnotationEnum;
import
com.google.gwt.dev.javac.TypeOracleMediator.MyClassVisitor.MyAnnotationVisitor;
import
com.google.gwt.dev.javac.TypeOracleMediator.MyClassVisitor.MyFieldVisitor;
@@ -60,6 +62,7 @@
import com.google.gwt.dev.util.Name.InternalName;
import com.google.gwt.dev.util.Name.SourceName;
+import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
@@ -188,9 +191,9 @@
private final TypeParameterLookup lookup;
private JTypeParameter currentParam = null;
- private List<JClassType[]> bounds = null;
- private JClassType[] superClass = new JClassType[1];
- private List<JClassType[]> interfaces = new ArrayList<JClassType[]>();
+ private ArrayList<JType[]> bounds = null;
+ private JType[] superClass = new JType[1];
+ private List<JType[]> interfaces = new ArrayList<JType[]>();
public ResolveClassTypeVariables(TreeLogger logger, JRealClassType
type,
TypeParameterLookup lookup) {
@@ -204,7 +207,7 @@
int n = bounds.size();
JClassType[] boundTypes = new JClassType[n];
for (int i = 0; i < n; ++i) {
- boundTypes[i] = bounds.get(i)[0];
+ boundTypes[i] = (JClassType) bounds.get(i)[0];
}
currentParam.setBounds(boundTypes);
currentParam = null;
@@ -218,13 +221,13 @@
// told Object is the superclass and ignore it.
assert superClass[0].equals(typeOracle.getJavaLangObject());
} else {
- type.setSuperclass(superClass[0]);
+ type.setSuperclass((JClassType) superClass[0]);
}
superClass[0] = null;
}
- for (JClassType[] intfRef : interfaces) {
+ for (JType[] intfRef : interfaces) {
if (intfRef[0] != null) {
- type.addImplementedInterface(intfRef[0]);
+ type.addImplementedInterface((JClassType) intfRef[0]);
}
}
interfaces.clear();
@@ -238,7 +241,7 @@
@Override
public SignatureVisitor visitClassBound() {
- JClassType[] bound = new JClassType[1];
+ JType[] bound = new JClassType[1];
bounds.add(bound);
return new ResolveParameterizedType(logger, bound, lookup, null);
}
@@ -247,20 +250,20 @@
public void visitFormalTypeParameter(String name) {
finish();
currentParam = lookup.lookup(name);
- bounds = new ArrayList<JClassType[]>();
+ bounds = new ArrayList<JType[]>();
}
@Override
public SignatureVisitor visitInterface() {
finish();
- JClassType[] intf = new JClassType[1];
+ JType[] intf = new JType[1];
interfaces.add(intf);
return new ResolveParameterizedType(logger, intf, lookup, null);
}
@Override
public SignatureVisitor visitInterfaceBound() {
- JClassType[] bound = new JClassType[1];
+ JType[] bound = new JType[1];
bounds.add(bound);
return new ResolveParameterizedType(logger, bound, lookup, null);
}
@@ -273,12 +276,152 @@
}
/**
+ * Resolve a method given its generic signature, including return type,
+ * parameter types, and exceptions thrown.
+ */
+ public class ResolveMethodSignature extends EmptySignatureVisitor {
+
+ private final TreeLogger logger;
+ private final JAbstractMethod method;
+ private final TypeParameterLookup typeParamLookup;
+ private final boolean hasReturnType;
+ private final MyMethodVisitor methodData;
+
+ private JType[] returnType = new JType[1];
+ private List<JType[]> params = new ArrayList<JType[]>();
+ private List<JType[]> exceptions = new ArrayList<JType[]>();
+ private JTypeParameter currentParam = null;
+ private ArrayList<JType[]> bounds = null;
+
+ public ResolveMethodSignature(TreeLogger logger, JAbstractMethod
method,
+ TypeParameterLookup typeParamLookup, boolean hasReturnType,
+ MyMethodVisitor methodData) {
+ this.logger = logger;
+ this.method = method;
+ this.typeParamLookup = typeParamLookup;
+ this.hasReturnType = hasReturnType;
+ this.methodData = methodData;
+ }
+
+ /**
+ * @return true if resolution succeeded.
+ */
+ public boolean finish() {
+ boolean failed = false;
+
+ finishBound();
+
+ // Set return type
+ if (hasReturnType) {
+ failed |= (returnType[0] == null);
+ ((JMethod) method).setReturnType(returnType[0]);
+ }
+
+ // Create arguments
+ Type[] argTypes = methodData.getArgTypes();
+ String[] argNames = methodData.getArgNames();
+ List<MyAnnotationVisitor>[] argAnnotations =
methodData.getArgAnnotations();
+ if (argTypes.length != params.size()) {
+ // TODO(jat): remove this check
+ throw new IllegalStateException(
+ "Arg count mismatch between bytecode and signature");
+ }
+ for (int i = 0; i < argTypes.length; ++i) {
+ JType argType = params.get(i)[0];
+ if (argType == null) {
+ failed = true;
+ continue;
+ }
+ // Try to resolve annotations, ignore any that fail.
+ Map<Class<? extends Annotation>, Annotation> declaredAnnotations =
new HashMap<Class<? extends Annotation>, Annotation>();
+ resolveAnnotations(logger, argAnnotations[i], declaredAnnotations);
+
+ // JParameter adds itself to the method
+ new JParameter(method, argType, argNames[i], declaredAnnotations);
+ }
+
+ // Handle thrown exceptions
+ for (JType[] exc : exceptions) {
+ if (exc[0] == null) {
+ failed = true;
+ continue;
+ }
+ method.addThrows(exc[0]);
+ }
+ return !failed;
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ assert false : "visitArrayType called on ResolveClassTypeVariables";
+ return null;
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ JType[] bound = new JClassType[1];
+ bounds.add(bound);
+ return new ResolveParameterizedType(logger, bound, typeParamLookup,
null);
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ JType[] exc = new JType[1];
+ exceptions.add(exc);
+ return new ResolveParameterizedType(logger, exc, typeParamLookup,
null);
+ }
+
+ @Override
+ public void visitFormalTypeParameter(String name) {
+ finishBound();
+ currentParam = typeParamLookup.lookup(name);
+ bounds = new ArrayList<JType[]>();
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ JType[] bound = new JType[1];
+ bounds.add(bound);
+ return new ResolveParameterizedType(logger, bound, typeParamLookup,
null);
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ JType[] param = new JType[1];
+ params.add(param);
+ // TODO(jat): enclosing type for local classes?
+ return new ResolveParameterizedType(logger, param, typeParamLookup,
null);
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ // TODO(jat): enclosing type for local classes?
+ return new ResolveParameterizedType(logger, returnType,
typeParamLookup,
+ null);
+ }
+
+ private void finishBound() {
+ if (currentParam != null) {
+ int n = bounds.size();
+ JClassType[] boundTypes = new JClassType[n];
+ for (int i = 0; i < n; ++i) {
+ boundTypes[i] = (JClassType) bounds.get(i)[0];
+ }
+ currentParam.setBounds(boundTypes);
+ currentParam = null;
+ // TODO(jat): remove after debugging phase
+ bounds = null;
+ }
+ }
+ }
+
+ /**
* Resolve a single parameterized type.
*/
public class ResolveParameterizedType extends EmptySignatureVisitor {
private final TreeLogger logger;
- private final JClassType[] returnTypeRef;
+ private final JType[] returnTypeRef;
private final TypeParameterLookup lookup;
private final char wildcardMatch;
private final JClassType enclosingClass;
@@ -293,13 +436,13 @@
* @param result "pointer" to return location, ie. 1-element array
*/
public ResolveParameterizedType(TreeLogger logger,
- JClassType[] returnTypeRef, TypeParameterLookup lookup,
+ JType[] returnTypeRef, TypeParameterLookup lookup,
JClassType enclosingClass) {
this(logger, returnTypeRef, lookup, enclosingClass, '=');
}
public ResolveParameterizedType(TreeLogger logger,
- JClassType[] returnTypeRef, TypeParameterLookup lookup,
+ JType[] returnTypeRef, TypeParameterLookup lookup,
JClassType enclosingClass,
char wildcardMatch) {
this.logger = logger;
@@ -316,6 +459,42 @@
}
@Override
+ public void visitBaseType(char descriptor) {
+ switch (descriptor) {
+ case 'V':
+ returnTypeRef[0] = JPrimitiveType.VOID;
+ break;
+ case 'B':
+ returnTypeRef[0] = JPrimitiveType.BYTE;
+ break;
+ case 'J':
+ returnTypeRef[0] = JPrimitiveType.LONG;
+ break;
+ case 'Z':
+ returnTypeRef[0] = JPrimitiveType.BOOLEAN;
+ break;
+ case 'I':
+ returnTypeRef[0] = JPrimitiveType.INT;
+ break;
+ case 'S':
+ returnTypeRef[0] = JPrimitiveType.SHORT;
+ break;
+ case 'C':
+ returnTypeRef[0] = JPrimitiveType.CHAR;
+ break;
+ case 'F':
+ returnTypeRef[0] = JPrimitiveType.FLOAT;
+ break;
+ case 'D':
+ returnTypeRef[0] = JPrimitiveType.DOUBLE;
+ break;
+ default:
+ throw new IllegalStateException("Unrecognized base type "
+ + descriptor);
+ }
+ }
+
+ @Override
public void visitClassType(String internalName) {
outerClass = enclosingClass;
InternalName className = Name.internalName(internalName);
@@ -339,7 +518,7 @@
// successively refine the class by going into its inner classes.
assert returnTypeRef[0] != null;
resolveGenerics();
- outerClass = returnTypeRef[0];
+ outerClass = (JClassType) returnTypeRef[0];
JClassType searchClass = outerClass;
try {
JParameterizedType pt = searchClass.isParameterized();
@@ -393,7 +572,6 @@
for (int i = 0; i < actual; ++i) {
typeArgs[i] = args.get(i)[0];
}
- args.clear();
try {
returnTypeRef[0] =
typeOracle.getParameterizedType(genericType, outerClass,
typeArgs);
@@ -402,6 +580,7 @@
+ genericType + "<" + Arrays.deepToString(typeArgs) + ">",
e);
returnTypeRef[0] = genericType.getRawType();
}
+ args.clear();
}
}
for (int i = 0; i < arrayDepth; ++i) {
@@ -414,15 +593,15 @@
case '+':
// ? extends T
returnTypeRef[0] = typeOracle.getWildcardType(
- JWildcardType.BoundType.EXTENDS, returnTypeRef[0]);
+ JWildcardType.BoundType.EXTENDS, (JClassType)
returnTypeRef[0]);
break;
case '-':
// ? super T
returnTypeRef[0] = typeOracle.getWildcardType(
- JWildcardType.BoundType.SUPER, returnTypeRef[0]);
+ JWildcardType.BoundType.SUPER, (JClassType)
returnTypeRef[0]);
break;
}
- outerClass = returnTypeRef[0];
+ outerClass = (JClassType) returnTypeRef[0];
}
}
@@ -433,6 +612,49 @@
protected static class MyClassVisitor extends EmptyVisitor {
/**
+ * Type of this class {...@linkplain }
+ */
+ public enum ClassType {
+ TopLevel,
+
+ Inner {
+ @Override
+ public boolean hasHiddenConstructorArg() {
+ return true;
+ }
+ },
+
+ Nested,
+
+ Anonymous {
+ @Override
+ public boolean hasOuter() {
+ return true;
+ }
+ },
+
+ Local {
+ @Override
+ public boolean hasHiddenConstructorArg() {
+ return true;
+ }
+
+ @Override
+ public boolean hasOuter() {
+ return true;
+ }
+ };
+
+ public boolean hasHiddenConstructorArg() {
+ return false;
+ }
+
+ public boolean hasOuter() {
+ return false;
+ }
+ }
+
+ /**
* Collect data from a single field.
*/
public static class MyFieldVisitor extends EmptyVisitor {
@@ -656,6 +878,7 @@
protected static class MyMethodVisitor extends EmptyVisitor {
private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
private List<MyAnnotationVisitor> annotations = new
ArrayList<MyAnnotationVisitor>();
private String name;
private String desc;
@@ -663,20 +886,37 @@
private String[] exceptions;
private Type[] argTypes;
private String[] argNames;
+ private List<MyAnnotationVisitor>[] paramAnnots;
private boolean actualArgNames = false;
private int access;
- public MyMethodVisitor(int access, String name, String desc, String
signature,
- String[] exceptions) {
+ public MyMethodVisitor(ClassType classType, int access, String name,
+ String desc, String signature, String[] exceptions) {
this.access = access;
this.name = name;
this.desc = desc;
this.signature = signature;
this.exceptions = exceptions;
argTypes = Type.getArgumentTypes(desc);
+ // Non-static instance methods and constructors of non-static inner
+ // classes have an extra synthetic parameter that isn't in the
source,
+ // so we remove it.
+ if (classType.hasHiddenConstructorArg() && "<init>".equals(name)) {
+ // remove "this$1" as a parameter
+ int skip = 1;
+ int n = argTypes.length - skip;
+ if (n < 0) {
+ boolean stophere = true;
+ }
+ Type[] newArgTypes = new Type[n];
+ System.arraycopy(argTypes, skip, newArgTypes, 0, n);
+ argTypes = newArgTypes;
+ }
argNames = new String[argTypes.length];
+ paramAnnots = new List[argTypes.length];
for (int i = 0; i < argNames.length; ++i) {
argNames[i] = "arg" + i;
+ paramAnnots[i] = new ArrayList<MyAnnotationVisitor>();
}
}
@@ -694,6 +934,10 @@
return annotations;
}
+ public List<MyAnnotationVisitor>[] getArgAnnotations() {
+ return paramAnnots;
+ }
+
/**
* @return the argNames
*/
@@ -760,6 +1004,7 @@
String signature, Label start, Label end, int index) {
if ((access & Opcodes.ACC_STATIC) == 0) {
// adjust for "this"
+ // TODO(jat): do we need to account for this$0 in inner classes?
--index;
}
// TODO(jat): is it safe to assume parameter slots don't get
reused?
@@ -769,6 +1014,14 @@
argNames[index] = name;
}
}
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(int parameter,
+ String desc, boolean visible) {
+ MyAnnotationVisitor av = new MyAnnotationVisitor(desc, visible);
+ paramAnnots[parameter].add(av);
+ return av;
+ }
}
static class AnnotationEnum {
@@ -810,6 +1063,7 @@
private String outerClass;
private String outerMethodName;
private String outerMethodDesc;
+ private ClassType classType = ClassType.TopLevel;
public MyClassVisitor(byte[] bytes) {
this.bytes = bytes;
@@ -837,6 +1091,13 @@
}
/**
+ * @return the class type.
+ */
+ public ClassType getClassType() {
+ return classType;
+ }
+
+ /**
* @return the fields
*/
public List<MyFieldVisitor> getFields() {
@@ -958,6 +1219,10 @@
public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) {
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ("this$1".equals(name) && classType == ClassType.Anonymous) {
+ // TODO(jat): !!! really nasty hack
+ classType = ClassType.Inner;
+ }
// skip synthetic fields
return null;
}
@@ -984,8 +1249,26 @@
// If this inner class is ourselves, merge the access flags, since
// static, for example, only appears in the InnerClass attribute.
if (this.name.equals(Name.internalName(name))) {
- // TODO(jat): should we only pull in a subset of these flags?
- this.access |= access;
+ // TODO(jat): should we only pull in a subset of these flags? Use
only
+ // these flags, or what? For now, just grab ACC_STATIC
+ int staticFlag = (access & Opcodes.ACC_STATIC);
+ this.access |= staticFlag;
+ switch (classType) {
+ case TopLevel:
+ classType = staticFlag == 0 ? ClassType.Inner :
ClassType.Nested;
+ break;
+ case Anonymous:
+ if (innerName != null) {
+ classType = ClassType.Local;
+ }
+ break;
+ case Inner:
+ // Already marked as inner class by the synthetic this$1 field
+ break;
+ default:
+ throw new IllegalStateException(
+ "Unexpected INNERCLASS with type of " + classType);
+ }
}
}
@@ -996,9 +1279,8 @@
// skip synthetic methods
return null;
}
- // TODO(jat): generic signature for methods
- MyMethodVisitor mv = new MyMethodVisitor(access, name, desc,
signature,
- exceptions);
+ MyMethodVisitor mv = new MyMethodVisitor(classType, access, name,
+ desc, signature, exceptions);
methods.add(mv);
return mv;
}
@@ -1008,6 +1290,7 @@
this.outerClass = owner;
this.outerMethodName = name;
this.outerMethodDesc = desc;
+ classType = ClassType.Anonymous; // Could be Local, catch that later
}
/**
@@ -1048,10 +1331,10 @@
}
public void pushScope(JTypeParameter[] typeParams) {
- if (typeParams == null || typeParams.length == 0) {
- // ignore empty scopes
- return;
- }
+// if (typeParams == null || typeParams.length == 0) {
+// // ignore empty scopes
+// return;
+// }
scopeStack.addFirst(buildScope(typeParams));
}
@@ -1169,6 +1452,61 @@
return null;
}
}
+ private static void getDescriptor(StringBuffer buf, JType type) {
+ JType t = type;
+ while (true) {
+ JPrimitiveType primitive = t.isPrimitive();
+ if (primitive != null) {
+ char ch;
+ if (primitive == JPrimitiveType.INT) {
+ ch = 'I';
+ } else if (t == JPrimitiveType.VOID) {
+ ch = 'V';
+ } else if (t == JPrimitiveType.BOOLEAN) {
+ ch = 'Z';
+ } else if (t == JPrimitiveType.BYTE) {
+ ch = 'B';
+ } else if (t == JPrimitiveType.CHAR) {
+ ch = 'C';
+ } else if (t == JPrimitiveType.SHORT) {
+ ch = 'S';
+ } else if (t == JPrimitiveType.DOUBLE) {
+ ch = 'D';
+ } else if (t == JPrimitiveType.FLOAT) {
+ ch = 'F';
+ } else if (t == JPrimitiveType.LONG) {
+ ch = 'J';
+ } else {
+ // TODO(jat): remove safety check
+ throw new IllegalStateException("Unexpected primitive type " +
t);
+ }
+ buf.append(ch);
+ return;
+ } else if (t.isArray() != null) {
+ buf.append('[');
+ t = t.isArray().getComponentType();
+ } else if (t.isTypeParameter() != null) {
+ t = t.isTypeParameter().getFirstBound();
+ } else {
+ buf.append('L').append(t.getQualifiedBinaryName().replace('.',
+ '/')).append(';');
+ return;
+ }
+ }
+ }
+
+ private static String getMethodDescriptor(JType returnType,
+ JType[] argumentTypes) {
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < argumentTypes.length; ++i) {
+ getDescriptor(buf, argumentTypes[i]);
+ }
+ buf.append(')');
+ getDescriptor(buf, returnType);
+ return buf.toString();
+ }
+
/**
* Returns <code>true</code> if this name is the special package-info
type
* name.
@@ -1423,9 +1761,14 @@
private MyClassVisitor processClass(CompiledClass compiledClass) {
byte[] classBytes = compiledClass.getBytes();
ClassReader reader = new ClassReader(classBytes);
- MyClassVisitor cv = new MyClassVisitor(classBytes);
+ MyClassVisitor mcv = new MyClassVisitor(classBytes);
+ ClassVisitor cv = mcv;
+ if ("java/util/Collections$1".equals(
+ compiledClass.getInternalName().toString())) {
+ cv = new TraceClassVisitor(cv, new PrintWriter(System.out));
+ }
reader.accept(cv, 0);
- return cv;
+ return mcv;
}
private boolean resolveAnnotation(TreeLogger logger,
@@ -1535,10 +1878,14 @@
}
private boolean resolveBoundsForTypeParameters(TreeLogger logger,
- JRealClassType type, JAbstractMethod method, MyMethodVisitor
methodData) {
- // TODO(jat): !! implement resolveBoundsForTypeParameters
+ JTypeParameter[] typeParams, TypeParameterLookup typeParamLookup) {
// logger.log(TreeLogger.WARN,
// "Unimplemented: resolveBoundsForTypeParameters");
+ if (typeParams == null || typeParams.length == 0) {
+ return true;
+ }
+ for (JTypeParameter typeParam : typeParams) {
+ }
return true;
}
@@ -1580,29 +1927,56 @@
+ outerType.getQualifiedSourceName());
return false;
}
+ // Make sure our outer class has been resolved.
+ if (!resolveClass(logger, outerType)) {
+ return false;
+ }
assert outerType instanceof JRealClassType;
JRealClassType outer = (JRealClassType) outerType;
String methodName = classData.getOuterMethodName();
String methodDesc = classData.getOuterMethodDesc();
if (methodName != null) {
- Type[] argTypes = Type.getArgumentTypes(methodDesc);
- int n = argTypes.length;
- JType[] resolvedArgTypes = new JType[n];
- for (int i = 0; i < n; ++i) {
- resolvedArgTypes[i] = resolveType(logger, argTypes[i]);
- }
- JAbstractMethod method;
- try {
- // TODO(jat): !! inner classes inside a <clinit>?
- if ("<init>".equals(methodName)) {
- method = outer.getConstructor(resolvedArgTypes);
- } else {
- method = outer.getMethod(methodName, resolvedArgTypes);
+ JAbstractMethod method = null;
+ // TODO(jat): !! inner classes inside a <clinit>?
+ if ("<init>".equals(methodName)) {
+ MyClassVisitor outerClassData = classMap.get(
+ Name.binaryName(outer).toInternalName());
+ if (outerClassData.getClassType().hasHiddenConstructorArg()) {
+ // strip out first parameter from descriptor since it is
synthetic
+ methodDesc = methodDesc.replaceAll("\\(L[^;]*;", "(");
+ }
+ for (JConstructor m : outer.getConstructors()) {
+ JParameter[] parameters = m.getParameters();
+ int n = parameters.length;
+ JType[] argTypes = new JType[n];
+ for (int i = 0; i < n; ++i) {
+ argTypes[i] = parameters[i].getType();
+ }
+ String desc = getMethodDescriptor(JPrimitiveType.VOID,
+ argTypes);
+ if (methodDesc.equals(desc)) {
+ method = m;
+ break;
+ }
}
- } catch (NotFoundException e) {
+ } else {
+ for (JMethod m : outer.getOverloads(methodName)) {
+ JParameter[] parameters = m.getParameters();
+ int n = parameters.length;
+ JType[] argTypes = new JType[n];
+ for (int i = 0; i < n; ++i) {
+ argTypes[i] = parameters[i].getType();
+ }
+ String desc = getMethodDescriptor(m.getReturnType(), argTypes);
+ if (methodDesc.equals(desc)) {
+ method = m;
+ break;
+ }
+ }
+ }
+ if (method == null) {
logger.log(TreeLogger.ERROR, "Unable to find method " +
methodName
- + "(" + Arrays.deepToString(resolvedArgTypes) + ") in "
- + outer.getQualifiedSourceName(), e);
+ + methodDesc + " in " + outer.getQualifiedSourceName());
return false;
}
JTypeParameter[] typeParams = method.getTypeParameters();
@@ -1718,7 +2092,22 @@
jfield.addModifierBits(mapBits(ASM_TO_SHARED_MODIFIERS,
field.getAccess()));
- JType fieldType = resolveType(logger, Type.getType(field.getDesc()));
+ String signature = field.getSignature();
+ JType fieldType;
+ if (signature != null) {
+ SignatureReader reader = new SignatureReader(signature);
+ JType[] fieldTypeRef = new JType[1];
+ reader.acceptType(new ResolveParameterizedType(logger, fieldTypeRef,
+ typeParamLookup, type));
+ fieldType = fieldTypeRef[0];
+// TraceSignatureVisitor trace = new TraceSignatureVisitor(
+// methodData.getAccess());
+// reader.acceptType(trace);
+// System.err.println("Field " + name + ": " +
trace.getDeclaration());
+
+ } else {
+ fieldType = resolveType(logger, Type.getType(field.getDesc()));
+ }
if (fieldType == null) {
return false;
}
@@ -1744,6 +2133,7 @@
// resolve the bounds on each JTypeParameter object.
JTypeParameter[] typeParams =
collectTypeParams(methodData.getSignature());
+ typeParamLookup.pushScope(typeParams);
boolean hasReturnType = true;
if ("<init>".equals(name)) {
method = new JConstructor(type, name, declaredAnnotations,
@@ -1758,21 +2148,6 @@
method = new JMethod(type, name, declaredAnnotations, typeParams);
}
}
- if (!resolveBoundsForTypeParameters(logger, type, method, methodData))
{
- return false;
- }
-
- // TODO(jat): !! handle generics in return type, params, and throws
-
- if (hasReturnType) {
-
- Type returnType = Type.getReturnType(methodData.getDesc());
- JType returnJType = resolveType(logger, returnType);
- if (returnJType == null) {
- return false;
- }
- ((JMethod) method).setReturnType(returnJType);
- }
// Copy modifier flags
method.addModifierBits(mapBits(ASM_TO_SHARED_MODIFIERS,
@@ -1782,13 +2157,50 @@
method.addModifierBits(Shared.MOD_PUBLIC | Shared.MOD_ABSTRACT);
}
- if (!resolveParameters(logger, method, methodData)) {
- return false;
+ if ((methodData.getAccess() & Opcodes.ACC_VARARGS) != 0) {
+ method.setVarArgs();
}
- if (!resolveThrows(logger, method, methodData)) {
- return false;
+ if (!methodData.hasActualArgNames()) {
+ method.setFakeArgNames();
}
+// if (!resolveBoundsForTypeParameters(logger, type, method, methodData,
+// typeParamLookup)) {
+// return false;
+// }
+
+ String signature = methodData.getSignature();
+ if (signature != null) {
+ // If we have a signature, use it for superclass and interfaces
+ SignatureReader reader = new SignatureReader(signature);
+ ResolveMethodSignature resolver = new ResolveMethodSignature(logger,
+ method, typeParamLookup, hasReturnType, methodData);
+// TraceSignatureVisitor trace = new TraceSignatureVisitor(
+// methodData.getAccess());
+// reader.accept(trace);
+// System.err.println("Method " + name + ": " +
trace.getDeclaration());
+ reader.accept(resolver);
+ if (!resolver.finish()) {
+ return false;
+ }
+ } else {
+ if (hasReturnType) {
+ Type returnType = Type.getReturnType(methodData.getDesc());
+ JType returnJType = resolveType(logger, returnType);
+ if (returnJType == null) {
+ return false;
+ }
+ ((JMethod) method).setReturnType(returnJType);
+ }
+
+ if (!resolveParameters(logger, method, methodData)) {
+ return false;
+ }
+ if (!resolveThrows(logger, method, methodData)) {
+ return false;
+ }
+ }
+ typeParamLookup.popScope();
return true;
}
@@ -1806,7 +2218,6 @@
private boolean resolveParameters(TreeLogger logger, JAbstractMethod
method,
MyMethodVisitor methodData) {
- // TODO(jat): !! varargs
Type[] argTypes = methodData.getArgTypes();
String[] argNames = methodData.getArgNames();
for (int i = 0; i < argTypes.length; ++i) {
@@ -1821,12 +2232,6 @@
// JParameter adds itself to the method
new JParameter(method, argType, argNames[i], declaredAnnotations);
- }
- if ((methodData.getAccess() & Opcodes.ACC_VARARGS) != 0) {
- method.setVarArgs();
- }
- if (!methodData.hasActualArgNames()) {
- method.setFakeArgNames();
}
return true;
}
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---