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
-~----------~----~----~----~------~----~------~--~---

Reply via email to