/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.javac;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.dev.asm.ClassReader;
import com.google.gwt.dev.asm.ClassVisitor;
import com.google.gwt.dev.asm.Opcodes;
import com.google.gwt.dev.asm.Type;
import com.google.gwt.dev.asm.signature.SignatureReader;
import com.google.gwt.dev.asm.util.TraceClassVisitor;
import com.google.gwt.dev.javac.asm.CollectAnnotationData;
import com.google.gwt.dev.javac.asm.CollectAnnotationData.AnnotationData;
import com.google.gwt.dev.javac.asm.CollectClassData;
import com.google.gwt.dev.javac.asm.CollectClassData.AnnotationEnum;
import com.google.gwt.dev.javac.asm.CollectFieldData;
import com.google.gwt.dev.javac.asm.CollectMethodData;
import com.google.gwt.dev.javac.asm.CollectTypeParams;
import com.google.gwt.dev.javac.asm.ResolveClassSignature;
import com.google.gwt.dev.javac.asm.ResolveMethodSignature;
import com.google.gwt.dev.javac.asm.ResolveTypeSignature;
import com.google.gwt.dev.javac.typemodel.JAbstractMethod;
import com.google.gwt.dev.javac.typemodel.JArrayType;
import com.google.gwt.dev.javac.typemodel.JClassType;
import com.google.gwt.dev.javac.typemodel.JField;
import com.google.gwt.dev.javac.typemodel.JGenericType;
import com.google.gwt.dev.javac.typemodel.JMethod;
import com.google.gwt.dev.javac.typemodel.JPackage;
import com.google.gwt.dev.javac.typemodel.JParameterizedType;
import com.google.gwt.dev.javac.typemodel.JRawType;
import com.google.gwt.dev.javac.typemodel.JRealClassType;
import com.google.gwt.dev.javac.typemodel.JTypeParameter;
import com.google.gwt.dev.javac.typemodel.JWildcardType;
import com.google.gwt.dev.javac.typemodel.TypeOracle;
import com.google.gwt.dev.javac.typemodel.TypeOracleUpdater;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Name.InternalName;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;

import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Builds or rebuilds a {@link com.google.gwt.core.ext.typeinfo.TypeOracle} from
 * a set of compilation units.
 */
public class CompilationUnitTypeOracleUpdater extends TypeOracleUpdater {

  /**
   * A container to hold all the information we need to add one type to the
   * TypeOracle.
   */
  static class TypeData {

    /**
     * Bytecode from compiled Java source.
     */
    private final byte[] byteCode;

    /**
     * Prepared information about this class.
     */
    private CollectClassData classData;

    /**
     * See {@link Type#getInternalName()}.
     */
    private final String internalName;

    /**
     * A timestamp as returned from {@link System#currentTimeMillis()}
     *
     * TODO(zundel): currently unused, add to JType later.
     */
    private final long lastModifiedTime;

    /**
     * Package name.
     */
    private final String packageName;

    /**
     * URL to fetch the source file from a class loader. If a method arg name is
     * requested, we may need to go back to this file and compile it.
     *
     * TODO(zundel): currently unused, add to JRealClassType later.
     */
    private final String sourceFileResourceName;

    /**
     * See {@link JType#getQualifiedSourceName()}.
     */
    private final String sourceName;

    protected TypeData(String packageName, String sourceName,
        String internalName, String sourceFileResourceName, byte[] classBytes,
        long lastModifiedTime) {
      this.packageName = packageName;
      this.sourceName = sourceName;
      this.internalName = internalName;
      this.sourceFileResourceName = sourceFileResourceName;
      this.byteCode = classBytes;
      this.lastModifiedTime = lastModifiedTime;
    }

    /**
     * Collects data about a class which only needs the bytecode and no TypeOracle
     * data structures. This is used to make the initial shallow identity pass for
     * creating JRealClassType/JGenericType objects.
     */
    synchronized CollectClassData getCollectClassData() {
      if (classData == null) {
        ClassReader reader = new ClassReader(byteCode);
        classData = new CollectClassData();
        ClassVisitor cv = classData;
        if (TRACE_CLASSES) {
          cv = new TraceClassVisitor(cv, new PrintWriter(System.out));
        }
        reader.accept(cv, 0);
      }
      return classData;
    }
  }

  /**
   * This context keeps common data so we don't have to pass it around between
   * methods for one pass of
   * {@link CompilationUnitTypeOracleUpdater#addNewTypes(TreeLogger, Collection, MethodArgNamesLookup)}
   * .
   */
  private class TypeOracleBuildContext {
    private final MethodArgNamesLookup allMethodArgs;

    // map of internal names to class visitors.
    private final Map<String, CollectClassData> classMap = new HashMap<String, CollectClassData>();
    // map of JRealType instances to lookup class visitors.
    private final HashMap<JRealClassType, CollectClassData> classMapType = new HashMap<JRealClassType, CollectClassData>();

    private final Resolver resolver = new CompilationUnitTypeOracleResolver(this);

    private TypeOracleBuildContext(MethodArgNamesLookup allMethodArgs) {
      this.allMethodArgs = allMethodArgs;
    }
  }

  private class CompilationUnitTypeOracleResolver implements Resolver {

    private final TypeOracleBuildContext context;

    public CompilationUnitTypeOracleResolver(TypeOracleBuildContext context) {
      this.context = context;
    }

    @Override
    public void addImplementedInterface(JRealClassType type, JClassType intf) {
      CompilationUnitTypeOracleUpdater.this.addImplementedInterface(type, intf);
    }

    @Override
    public void addThrows(JAbstractMethod method, JClassType exception) {
      CompilationUnitTypeOracleUpdater.this.addThrows(method, exception);
    }

    @Override
    public Map<String, JRealClassType> getInternalMapper() {
      return CompilationUnitTypeOracleUpdater.this.internalMapper;
    }

    @Override
    public TypeOracle getTypeOracle() {
      return CompilationUnitTypeOracleUpdater.this.typeOracle;
    }

    @Override
    public JMethod newMethod(JClassType type, String name,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
        JTypeParameter[] typeParams) {
      return CompilationUnitTypeOracleUpdater.this.newMethod(type, name,
          declaredAnnotations, typeParams);
    }

    @Override
    public void newParameter(JAbstractMethod method, JType argType,
        String argName,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
        boolean argNamesAreReal) {
      CompilationUnitTypeOracleUpdater.this.newParameter(method, argType, argName,
          declaredAnnotations, argNamesAreReal);
    }

    @Override
    public JRealClassType newRealClassType(JPackage pkg,
        String enclosingTypeName, boolean isLocalType, String className,
        boolean isIntf) {
      return CompilationUnitTypeOracleUpdater.this.newRealClassType(pkg, enclosingTypeName,
          className, isIntf);
    }

    @Override
    public boolean resolveAnnotation(TreeLogger logger,
        CollectAnnotationData annotVisitor,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
      return CompilationUnitTypeOracleUpdater.this.resolveAnnotation(logger, annotVisitor,
          declaredAnnotations);
    }

    @Override
    public boolean resolveAnnotations(TreeLogger logger,
        List<CollectAnnotationData> annotations,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
      return CompilationUnitTypeOracleUpdater.this.resolveAnnotations(logger, annotations,
          declaredAnnotations);
    }

    @Override
    public boolean resolveClass(TreeLogger logger, JRealClassType type) {
      return CompilationUnitTypeOracleUpdater.this.resolveClass(logger, type, context);
    }

    @Override
    public void setReturnType(JAbstractMethod method, JType returnType) {
      CompilationUnitTypeOracleUpdater.this.setReturnType(method, returnType);
    }

    @Override
    public void setSuperClass(JRealClassType type, JClassType superType) {
      CompilationUnitTypeOracleUpdater.this.setSuperClass(type, superType);
    }
}

  /**
   * Pairs of bits to convert from ASM Opcodes.* to Shared.* bitfields.
   */
  private static final int[] ASM_TO_SHARED_MODIFIERS = new int[]{
      Opcodes.ACC_PUBLIC, Shared.MOD_PUBLIC, //
      Opcodes.ACC_PRIVATE, Shared.MOD_PRIVATE, //
      Opcodes.ACC_PROTECTED, Shared.MOD_PROTECTED, //
      Opcodes.ACC_STATIC, Shared.MOD_STATIC, //
      Opcodes.ACC_FINAL, Shared.MOD_FINAL, //
      Opcodes.ACC_ABSTRACT, Shared.MOD_ABSTRACT, //
      Opcodes.ACC_VOLATILE, Shared.MOD_VOLATILE, //
      Opcodes.ACC_TRANSIENT, Shared.MOD_TRANSIENT, //
  };

  private static final JTypeParameter[] NO_TYPE_PARAMETERS = new JTypeParameter[0];

  /**
   * Turn on to trace class processing.
   */
  private static final boolean TRACE_CLASSES = false;

  /**
   * Suppress some warnings related to missing valiation.jar on classpath.
   */
  private static boolean warnedMissingValidationJar = false;

  private static JTypeParameter[] collectTypeParams(String signature) {
    if (signature != null) {
      List<JTypeParameter> params = new ArrayList<JTypeParameter>();
      SignatureReader reader = new SignatureReader(signature);
      reader.accept(new CollectTypeParams(params));
      return params.toArray(new JTypeParameter[params.size()]);
    }
    return NO_TYPE_PARAMETERS;
  }

  private static JTypeParameter[] getTypeParametersForClass(
      CollectClassData classData) {
    JTypeParameter[] typeParams = null;
    if (classData.getSignature() != null) {
      // TODO(jat): do we need to consider generic types w/ method type
      // params for local classes?
      typeParams = collectTypeParams(classData.getSignature());
    }
    return typeParams;
  }

  private static Class<?> getWrapperClass(Class<?> primitiveClass) {
    assert primitiveClass.isPrimitive();
    if (primitiveClass.equals(Integer.TYPE)) {
      return Integer.class;
    } else if (primitiveClass.equals(Boolean.TYPE)) {
      return Boolean.class;
    } else if (primitiveClass.equals(Byte.TYPE)) {
      return Byte.class;
    } else if (primitiveClass.equals(Character.TYPE)) {
      return Character.class;
    } else if (primitiveClass.equals(Short.TYPE)) {
      return Short.class;
    } else if (primitiveClass.equals(Long.TYPE)) {
      return Long.class;
    } else if (primitiveClass.equals(Float.TYPE)) {
      return Float.class;
    } else if (primitiveClass.equals(Double.TYPE)) {
      return Double.class;
    } else {
      throw new IllegalArgumentException(primitiveClass.toString()
          + " not a primitive class");
    }
  }

  /**
   * @return <code>true</code> if this name is the special package-info type
   *         name.
   */
  private static boolean isPackageInfoTypeName(String qname) {
    return "package-info".equals(qname);
  }

  /**
   * Returns true if this class is a non-static class inside a generic class.
   *
   * TODO(jat): do we need to consider the entire hierarchy?
   *
   * @param classData
   * @param enclosingClassData
   * @return true if this class is a non-static class inside a generic class
   */
  private static boolean nonStaticInsideGeneric(CollectClassData classData,
      CollectClassData enclosingClassData) {
    if (enclosingClassData == null
        || (classData.getAccess() & Opcodes.ACC_STATIC) != 0) {
      return false;
    }
    return getTypeParametersForClass(enclosingClassData) != null;
  }

  /**
   * Substitute the raw type if the supplied type is generic.
   *
   * @param type
   * @return original type or its raw type if it is generic
   */
  private static JType possiblySubstituteRawType(JType type) {
    if (type != null) {
      JGenericType genericType = (JGenericType) type.isGenericType();
      if (genericType != null) {
        type = genericType.getRawType();
      }
    }
    return type;
  }

  // map of internal names to classes
  final Map<String, JRealClassType> internalMapper = new HashMap<String, JRealClassType>();

  private final Set<JRealClassType> resolved = new HashSet<JRealClassType>();

  public CompilationUnitTypeOracleUpdater(TypeOracle typeOracle) {
    super(typeOracle);
  }

  /**
   * Adds new units to an existing TypeOracle.
   *
   * @param logger logger to use
   * @param typeDataList collection of data need to build types
   */
  public void addNewTypes(TreeLogger logger, Collection<TypeData> typeDataList) {
    addNewTypes(logger, typeDataList, new MethodArgNamesLookup());
  }

  /**
   * Adds new units to an existing TypeOracle.
   *
   * @param logger logger to use
   * @param typeDataList collection of data need to build types. (Doesn't retain
   *                     references to TypeData instances.)
   * @param argsLookup Allows the caller to pass the method argument names which
   *          are not normally available in bytecode.
   */
  public void addNewTypes(TreeLogger logger, Collection<TypeData> typeDataList,
      MethodArgNamesLookup argsLookup) {
    Event typeOracleUpdaterEvent = SpeedTracerLogger.start(CompilerEventType.TYPE_ORACLE_UPDATER);

    // First collect all class data.
    Event visitClassFileEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase", "Visit Class Files");
    TypeOracleBuildContext context = new TypeOracleBuildContext(argsLookup);

    for (TypeData typeData : typeDataList) {
      CollectClassData cv = typeData.getCollectClassData();
      // skip any classes that can't be referenced by name outside of
      // their local scope, such as anonymous classes and method-local classes
      if (!cv.hasNoExternalName()) {
        context.classMap.put(typeData.internalName, cv);
      }
    }
    visitClassFileEvent.end();

    Event identityEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase", "Establish Identity");
    // Perform a shallow pass to establish identity for new and old types.
    Set<JRealClassType> unresolvedTypes = new LinkedHashSet<JRealClassType>();
    for (TypeData typeData : typeDataList) {
      CollectClassData cv = context.classMap.get(typeData.internalName);
      if (cv == null) {
        // ignore classes that were skipped earlier
        continue;
      }
      JRealClassType type = createType(typeData, unresolvedTypes, context);
      if (type != null) {
        internalMapper.put(typeData.internalName, type);
        context.classMapType.put(type, cv);
      }
    }
    identityEvent.end();

    Event resolveEnclosingEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase",
        "Resolve Enclosing Classes");
    // Hook up enclosing types
    TreeLogger branch = logger.branch(TreeLogger.SPAM,
        "Resolving enclosing classes");
    for (Iterator<JRealClassType> it = unresolvedTypes.iterator(); it.hasNext();) {
      JRealClassType type = it.next();
      if (!resolveEnclosingClass(branch, type, context)) {
        // already logged why it failed, don't try and use it further
        it.remove();
      }
    }
    resolveEnclosingEvent.end();

    Event resolveUnresolvedEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase",
        "Resolve Unresolved Types");
    // Resolve unresolved types.
    for (JRealClassType type : unresolvedTypes) {
      branch = logger.branch(TreeLogger.SPAM, "Resolving "
          + type.getQualifiedSourceName());
      if (!resolveClass(branch, type, context)) {
        // already logged why it failed.
        // TODO: should we do anything else here?
      }
    }
    resolveUnresolvedEvent.end();

    Event finishEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase", "Finish");
    super.finish();
    finishEvent.end();

    // no longer needed
    context = null;
    typeOracleUpdaterEvent.end();
  }

  /**
   * Adds new units to an existing TypeOracle.
   *
   * @param logger logger to use
   * @param units collection of compilation units to process
   */
  public void addNewUnits(TreeLogger logger, Collection<CompilationUnit> units) {
    Collection<TypeData> classDataList = new ArrayList<TypeData>();

    // Create method args data for types to add
    MethodArgNamesLookup argsLookup = new MethodArgNamesLookup();
    for (CompilationUnit unit : units) {
      argsLookup.mergeFrom(unit.getMethodArgs());
    }

    // Create list including byte code for each type to add
    for (CompilationUnit unit : units) {
      for (CompiledClass cc : unit.getCompiledClasses()) {
        TypeData data = new TypeData(cc.getPackageName(), cc.getSourceName(), cc.getInternalName(),
            null, cc.getBytes(), cc.getUnit().getLastModified());
        classDataList.add(data);
      }
    }

    // Add the new types to the type oracle build in progress.
    addNewTypes(logger, classDataList, argsLookup);
  }

  /**
   * @return a map from binary class names to JRealClassType.
   */
  public Map<String, JRealClassType> getInternalMapper() {
    return internalMapper;
  }

  /**
   * Intended for unit testing only.
   *
   * @return a mocked up version of this updater's resolver.
   */
  public Resolver getMockResolver() {
    return new CompilationUnitTypeOracleResolver(
        new TypeOracleBuildContext(new MethodArgNamesLookup()));
  }

  /**
   * @return the TypeOracle managed by the updater.
   */
  public TypeOracle getTypeOracle() {
    return typeOracle;
  }

  private Annotation createAnnotation(TreeLogger logger,
      Class<? extends Annotation> annotationClass, AnnotationData annotData) {
    // Make a copy before we mutate the collection.
    Map<String, Object> values = new HashMap<String, Object>(annotData.getValues());
    for (Map.Entry<String, Object> entry : values.entrySet()) {
      Method method = null;
      Throwable caught = null;
      try {
        method = annotationClass.getMethod(entry.getKey());
        entry.setValue(resolveAnnotationValue(logger, method.getReturnType(),
            entry.getValue()));
      } catch (SecurityException e) {
        caught = e;
      } catch (NoSuchMethodException e) {
        caught = e;
      }
      if (caught != null) {
        logger.log(TreeLogger.WARN, "Exception resolving "
            + annotationClass.getCanonicalName() + "." + entry.getKey(), caught);
        return null;
      }
    }
    return AnnotationProxyFactory.create(annotationClass, values);
  }

  /**
   * Doesn't retain a reference to the TypeData.
   */
  private JRealClassType createType(TypeData typeData,
      CollectClassData collectClassData, CollectClassData enclosingClassData) {
    int access = collectClassData.getAccess();
    String qualifiedSourceName = typeData.sourceName;
    String className = Shared.getShortName(qualifiedSourceName);
    JRealClassType resultType = null;
    String jpkgName = typeData.packageName;
    JPackage pkg = typeOracle.getOrCreatePackage(jpkgName);
    boolean isIntf = (access & Opcodes.ACC_INTERFACE) != 0;
    assert !collectClassData.hasNoExternalName();
    String enclosingTypeName = null;
    if (enclosingClassData != null) {
      enclosingTypeName = InternalName.toSourceName(InternalName.getClassName(enclosingClassData.getName()));
    }
    if ((access & Opcodes.ACC_ANNOTATION) != 0) {
      resultType = newAnnotationType(pkg, enclosingTypeName, className);
    } else if ((access & Opcodes.ACC_ENUM) != 0) {
      resultType = newEnumType(pkg, enclosingTypeName, className);
    } else {
      JTypeParameter[] typeParams = getTypeParametersForClass(collectClassData);
      if ((typeParams != null && typeParams.length > 0)
          || nonStaticInsideGeneric(collectClassData, enclosingClassData)) {
        resultType = new JGenericType(typeOracle, pkg, enclosingTypeName,
            className, isIntf, typeParams);
      } else {
        resultType = newRealClassType(pkg, enclosingTypeName, className, isIntf);
      }
    }

    /*
     * Add modifiers since these are needed for
     * TypeOracle.getParameterizedType's error checking code.
     */
    resultType.addModifierBits(mapBits(ASM_TO_SHARED_MODIFIERS, access));
    if (isIntf) {
      // Always add implicit modifiers on interfaces.
      resultType.addModifierBits(Shared.MOD_STATIC | Shared.MOD_ABSTRACT);
    }

    /*
     * Add lastModified time from compilation unit
     */
    resultType.addLastModifiedTime(typeData.lastModifiedTime);

    return resultType;
  }

  /**
   * Doesn't retain a reference to the TypeData.
   */
  private JRealClassType createType(TypeData typeData,
      Set<JRealClassType> unresolvedTypes,
      TypeOracleBuildContext context) {
    CollectClassData collectClassData = context.classMap.get(typeData.internalName);
    String outerClassName = collectClassData.getOuterClass();
    CollectClassData enclosingClassData = null;
    if (outerClassName != null) {
      enclosingClassData = context.classMap.get(outerClassName);
      if (enclosingClassData == null) {
        // if our enclosing class was skipped, skip this one too
        return null;
      }
    }
    JRealClassType realClassType = createType(typeData, collectClassData,
        enclosingClassData);
    unresolvedTypes.add(realClassType);
    return realClassType;
  }

  private Class<? extends Annotation> getAnnotationClass(TreeLogger logger,
      AnnotationData annotData) {
    Type type = Type.getType(annotData.getDesc());
    String typeName = type.getClassName();
    try {
      Class<?> clazz = Class.forName(typeName, false,
          Thread.currentThread().getContextClassLoader());
      if (!Annotation.class.isAssignableFrom(clazz)) {
        logger.log(TreeLogger.ERROR, "Type " + typeName
            + " is not an annotation");
        return null;
      }
      return clazz.asSubclass(Annotation.class);
    } catch (ClassNotFoundException e) {
      TreeLogger.Type level = TreeLogger.WARN;
      if (shouldSuppressUnresolvableAnnotation(logger, typeName)) {
        level = TreeLogger.DEBUG;
      }
      logger.log(level, "Ignoring unresolvable annotation type "
          + typeName);
      return null;
    }
  }

  @SuppressWarnings("unused")
  private Class<?> getClassLiteralForPrimitive(Type type) {
    switch (type.getSort()) {
      case Type.BOOLEAN:
        return Boolean.TYPE;
      case Type.BYTE:
        return Byte.TYPE;
      case Type.CHAR:
        return Character.TYPE;
      case Type.SHORT:
        return Short.TYPE;
      case Type.INT:
        return Integer.TYPE;
      case Type.LONG:
        return Long.TYPE;
      case Type.FLOAT:
        return Float.TYPE;
      case Type.DOUBLE:
        return Double.TYPE;
      case Type.VOID:
        return Void.TYPE;
      default:
        assert false : "Unexpected primitive type " + type;
        return null;
    }
  }

  /**
   * Map a bitset onto a different bitset.
   *
   * @param mapping int array containing a sequence of from/to pairs, each from
   *          entry should have exactly one bit set
   * @param input bitset to map
   * @return mapped bitset
   */
  private int mapBits(int[] mapping, int input) {
    int output = 0;
    for (int i = 0; i < mapping.length; i += 2) {
      if ((input & mapping[i]) != 0) {
        output |= mapping[i + 1];
      }
    }
    return output;
  }

  private boolean resolveAnnotation(TreeLogger logger,
      CollectAnnotationData annotVisitor,
      Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
    AnnotationData annotData = annotVisitor.getAnnotation();
    Class<? extends Annotation> annotationClass = getAnnotationClass(logger,
        annotData);
    if (annotationClass == null) {
      return false;
    }
    Annotation annotInstance = createAnnotation(logger, annotationClass,
        annotData);
    if (annotInstance == null) {
      return false;
    }
    declaredAnnotations.put(annotationClass, annotInstance);
    return true;
  }

  private boolean resolveAnnotations(TreeLogger logger,
      List<CollectAnnotationData> annotations,
      Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
    boolean succeeded = true;
    if (annotations != null) {
      for (CollectAnnotationData annotation : annotations) {
        succeeded &= resolveAnnotation(logger, annotation, declaredAnnotations);
      }
    }
    return succeeded;
  }

  @SuppressWarnings("unchecked")
  private Object resolveAnnotationValue(TreeLogger logger,
      Class<?> expectedType, Object value) {
    if (expectedType.isArray()) {
      Class<?> componentType = expectedType.getComponentType();
      if (!value.getClass().isArray()) {
        logger.log(TreeLogger.WARN, "Annotation error: expected array of "
            + componentType.getCanonicalName() + ", got "
            + value.getClass().getCanonicalName());
        return null;
      }
      if (componentType.isPrimitive()) {
        // primitive arrays are already resolved
        return value;
      }
      // resolve each element in the array
      int n = Array.getLength(value);
      Object newArray = Array.newInstance(componentType, n);
      for (int i = 0; i < n; ++i) {
        Object valueElement = Array.get(value, i);
        Object resolvedValue = resolveAnnotationValue(logger, componentType,
            valueElement);
        if (resolvedValue == null
            || !componentType.isAssignableFrom(resolvedValue.getClass())) {
          logger.log(TreeLogger.ERROR, "Annotation error: expected "
              + componentType + ", got " + resolvedValue);
        } else {
          Array.set(newArray, i, resolvedValue);
        }
      }
      return newArray;
    } else if (expectedType.isEnum()) {
      if (!(value instanceof AnnotationEnum)) {
        logger.log(TreeLogger.ERROR,
            "Annotation error: expected an enum value," + " but got " + value);
        return null;
      }
      AnnotationEnum annotEnum = (AnnotationEnum) value;
      Class<? extends Enum> enumType = expectedType.asSubclass(Enum.class);
      try {
        return Enum.valueOf(enumType, annotEnum.getValue());
      } catch (IllegalArgumentException e) {
        logger.log(TreeLogger.WARN, "Unable to resolve annotation value '"
            + annotEnum.getValue() + "' within enum type '"
            + enumType.getName() + "'");
        return null;
      }
    } else if (Annotation.class.isAssignableFrom(expectedType)) {
      if (!(value instanceof AnnotationData)) {
        logger.log(TreeLogger.WARN,
            "Annotation error: expected annotation type "
                + expectedType.getCanonicalName() + ", got "
                + value.getClass().getCanonicalName());
        return null;
      }
      AnnotationData annotData = (AnnotationData) value;
      Class<? extends Annotation> annotationClass = getAnnotationClass(logger,
          annotData);
      if (!expectedType.isAssignableFrom(annotationClass)) {
        logger.log(TreeLogger.WARN, "Annotation error: expected "
            + expectedType.getCanonicalName() + ", got "
            + annotationClass.getCanonicalName());
        return null;
      }
      return createAnnotation(logger, annotationClass, annotData);
    } else if (expectedType.isPrimitive()) {
      Class<?> wrapper = getWrapperClass(expectedType);
      return wrapper.cast(value);
    } else {
      if (expectedType.isAssignableFrom(value.getClass())) {
        return value;
      }
      if (Class.class.equals(expectedType)) {
        if (!(value instanceof Type)) {
          logger.log(TreeLogger.WARN, "Annotation error: expected a class "
              + "literal, but received " + value);
          return null;
        }
        Type valueType = (Type) value;
        // See if we can use a binary only class here
        try {
          return Class.forName(valueType.getClassName(), false,
              Thread.currentThread().getContextClassLoader());
        } catch (ClassNotFoundException e) {
          logger.log(TreeLogger.ERROR, "Annotation error: cannot resolve "
              + valueType.getClassName(), e);
          return null;
        }
      }
      // TODO(jat) asserts about other acceptable types
      return value;
    }
  }

  private JType resolveArray(Type type) {
    assert type.getSort() == Type.ARRAY;
    JType resolvedType = resolveType(type.getElementType());
    int dims = type.getDimensions();
    for (int i = 0; i < dims; ++i) {
      resolvedType = typeOracle.getArrayType(resolvedType);
    }
    return resolvedType;
  }

  private boolean resolveClass(TreeLogger logger, JRealClassType type,
      TypeOracleBuildContext context) {
    assert type != null;
    // Avoid cycles and useless computation.
    if (resolved.contains(type)) {
      return true;
    }
    resolved.add(type);

    // Make sure our enclosing type is resolved first.
    if (type.getEnclosingType() != null
        && !resolveClass(logger, type.getEnclosingType(), context)) {
      return false;
    }

    // Build a search list for type parameters to find their definition,
    // resolving enclosing classes as we go up.
    TypeParameterLookup typeParamLookup = new TypeParameterLookup();
    typeParamLookup.pushEnclosingScopes(type);

    CollectClassData classData = context.classMapType.get(type);
    assert classData != null;
    int access = classData.getAccess();

    assert (!classData.getClassType().hasNoExternalName());

    logger = logger.branch(TreeLogger.SPAM, "Found type '"
        + type.getQualifiedSourceName() + "'", null);

    // Handle package-info classes.
    if (isPackageInfoTypeName(type.getSimpleSourceName())) {
      return resolvePackage(logger, type, classData.getAnnotations());
    }

    // Resolve annotations
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
    resolveAnnotations(logger, classData.getAnnotations(), declaredAnnotations);
    addAnnotations(type, declaredAnnotations);

    String signature = classData.getSignature();

    /*
     * Note: Byte code from the OpenJDK compiler doesn't contain a type signature for non-static
     * inner classes of parameterized types that do not contain new parameters (but JDT compiled
     * byte code does). That can cause some differences in the way generic types are represented
     * in the type oracle.
     *
     * These differences also show up when using java.lang.reflect to look at types.
     */
    if (signature != null) {
      // If we have a signature, use it for superclass and interfaces
      SignatureReader reader = new SignatureReader(signature);
      ResolveClassSignature classResolver =
          new ResolveClassSignature(context.resolver, internalMapper, logger, type, typeParamLookup);
      reader.accept(classResolver);
      classResolver.finish();
    } else {
      // Set the super type for non-interfaces
      if ((access & Opcodes.ACC_INTERFACE) == 0) {
        String superName = classData.getSuperName();
        if (superName != null) {
          JClassType superType = internalMapper.get(superName);
          if (superType == null || !resolveClass(logger, superType, context)) {
            logger.log(TreeLogger.WARN, "Unable to resolve supertype "
                + superName);
            return false;
          }
          setSuperClass(type, (JClassType) possiblySubstituteRawType(superType));
        }
      }

      // Set interfaces
      for (String intfName : classData.getInterfaces()) {
        JClassType intf = internalMapper.get(intfName);
        if (intf == null || !resolveClass(logger, intf, context)) {
          logger.log(TreeLogger.WARN, "Unable to resolve interface " + intfName);
          return false;
        }
        addImplementedInterface(type,
            (JClassType) possiblySubstituteRawType(intf));
      }
    }
    if (((access & Opcodes.ACC_INTERFACE) == 0) && type.getSuperclass() == null) {
      // Only Object or interfaces should not have a superclass
      assert "java/lang/Object".equals(classData.getName());
    }

    // Process methods
    for (CollectMethodData method : classData.getMethods()) {
      if (!resolveMethod(logger, type, method, typeParamLookup, context)) {
        logger.log(TreeLogger.WARN, "Unable to resolve method " + method);
        return false;
      }
    }

    // Process fields
    // Track the next enum ordinal across resolveField calls.
    int[] nextEnumOrdinal = new int[]{0};
    for (CollectFieldData field : classData.getFields()) {
      if (!resolveField(logger, type, field, typeParamLookup, nextEnumOrdinal, context)) {
        logger.log(TreeLogger.WARN, "Unable to resolve field " + field);
        return false;
      }
    }

    return true;
  }

  private boolean resolveClass(TreeLogger logger, JType type, TypeOracleBuildContext context) {
    if (!(type instanceof JClassType)) {
      // non-classes are already resolved
      return true;
    }
    if (type instanceof JRealClassType) {
      return resolveClass(logger, (JRealClassType) type, context);
    }
    if (type instanceof JArrayType) {
      return resolveClass(logger, ((JArrayType) type).getComponentType(), context);
    }
    if (type instanceof JParameterizedType) {
      return resolveClass(logger, ((JParameterizedType) type).getBaseType(), context);
    }
    if (type instanceof JRawType) {
      return resolveClass(logger, ((JRawType) type).getBaseType(), context);
    }
    if (type instanceof JTypeParameter) {
      JTypeParameter typeParam = (JTypeParameter) type;
      if (!resolveClass(logger, typeParam.getDeclaringClass(), context)) {
        return false;
      }
      for (JClassType bound : typeParam.getBounds()) {
        if (!resolveClass(logger, bound, context)) {
          return false;
        }
      }
      return true;
    }
    if (type instanceof JWildcardType) {
      JWildcardType wildcard = (JWildcardType) type;
      for (JClassType bound : wildcard.getUpperBounds()) {
        if (!resolveClass(logger, bound, context)) {
          return false;
        }
      }
      for (JClassType bound : wildcard.getLowerBounds()) {
        if (!resolveClass(logger, bound, context)) {
          return false;
        }
      }
      return true;
    }
    return false;
  }

  private boolean resolveEnclosingClass(TreeLogger logger, JRealClassType type,
      TypeOracleBuildContext context) {
    assert type != null;
    if (type.getEnclosingType() != null) {
      return true;
    }
    // Find our enclosing class and set it
    CollectClassData classData = context.classMapType.get(type);
    assert classData != null;
    String outerClass = classData.getOuterClass();
    JRealClassType enclosingType = null;
    if (outerClass != null) {
      enclosingType = internalMapper.get(outerClass);
      // Ensure enclosing classes are resolved
      if (enclosingType != null) {
        if (!resolveEnclosingClass(logger, enclosingType, context)) {
          return false;
        }
        if (enclosingType.isGenericType() != null
            && (classData.getAccess() & (Opcodes.ACC_STATIC | Opcodes.ACC_INTERFACE)) != 0) {
          // If the inner class doesn't have access to it's enclosing type's
          // type variables, the enclosign type must be the raw type instead
          // of the generic type.
          JGenericType genericType = enclosingType.isGenericType();
          setEnclosingType(type, genericType.getRawType());
        } else {
          setEnclosingType(type, enclosingType);
        }
      }
    }
    return true;
  }

  private boolean resolveField(TreeLogger logger, JRealClassType type,
      CollectFieldData field, TypeParameterLookup typeParamLookup,
      int[] nextEnumOrdinal, TypeOracleBuildContext context) {
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
    resolveAnnotations(logger, field.getAnnotations(), declaredAnnotations);
    String name = field.getName();
    JField jfield;
    if ((field.getAccess() & Opcodes.ACC_ENUM) != 0) {
      assert (type.isEnum() != null);
      jfield = newEnumConstant(type, name, declaredAnnotations,
          nextEnumOrdinal[0]++);
    } else {
      JField newField = newField(type, name, declaredAnnotations);
      jfield = newField;
    }

    // Get modifiers.
    //
    addModifierBits(jfield, mapBits(ASM_TO_SHARED_MODIFIERS, field.getAccess()));

    String signature = field.getSignature();
    JType fieldType;
    if (signature != null) {
      SignatureReader reader = new SignatureReader(signature);
      JType[] fieldTypeRef = new JType[1];
      reader.acceptType(new ResolveTypeSignature(context.resolver, internalMapper,
          logger, fieldTypeRef, typeParamLookup, null));
      fieldType = fieldTypeRef[0];

    } else {
      fieldType = resolveType(Type.getType(field.getDesc()));
    }
    if (fieldType == null) {
      return false;
    }
    setFieldType(jfield, fieldType);
    return true;
  }

  private boolean resolveMethod(TreeLogger logger, JRealClassType type,
      CollectMethodData methodData, TypeParameterLookup typeParamLookup,
      TypeOracleBuildContext context) {
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
    resolveAnnotations(logger, methodData.getAnnotations(), declaredAnnotations);
    String name = methodData.getName();

    if ("<clinit>".equals(name)
        || (methodData.getAccess() & Opcodes.ACC_SYNTHETIC) != 0) {
      // Ignore the following and leave them out of TypeOracle:
      // - static initializers
      // - synthetic methods
      return true;
    }

    if (type.isEnum() != null && "<init>".equals(name)) {
      // Leave enum constructors out of TypeOracle
      return true;
    }

    JAbstractMethod method;

    // Declare the type parameters. We will pass them into the constructors for
    // JConstructor/JMethod/JAnnotatedMethod. Then, we'll do a second pass to
    // resolve the bounds on each JTypeParameter object.
    JTypeParameter[] typeParams = collectTypeParams(methodData.getSignature());

    typeParamLookup.pushScope(typeParams);
    boolean hasReturnType = true;
    if ("<init>".equals(name)) {
      name = type.getSimpleSourceName();
      method = newConstructor(type, name, declaredAnnotations, typeParams);
      hasReturnType = false;
    } else {
      if (type.isAnnotation() != null) {
        // TODO(jat): actually resolve the default annotation value.
        method = newAnnotationMethod(type, name, declaredAnnotations,
            typeParams, null);
      } else {
        method = newMethod(type, name, declaredAnnotations, typeParams);
      }
    }

    addModifierBits(method, mapBits(ASM_TO_SHARED_MODIFIERS,
        methodData.getAccess()));
    if (type.isInterface() != null) {
      // Always add implicit modifiers on interface methods.
      addModifierBits(method, Shared.MOD_PUBLIC | Shared.MOD_ABSTRACT);
    }

    if ((methodData.getAccess() & Opcodes.ACC_VARARGS) != 0) {
      setVarArgs(method);
    }

    String signature = methodData.getSignature();
    if (signature != null) {
      // If we have a signature, use it for superclass and interfaces
      SignatureReader reader = new SignatureReader(signature);
      ResolveMethodSignature methodResolver = new ResolveMethodSignature(
          context.resolver, logger, method, typeParamLookup, hasReturnType, methodData,
          methodData.getArgTypes(), methodData.getArgNames(),
          methodData.hasActualArgNames(), context.allMethodArgs);
      // TraceSignatureVisitor trace = new TraceSignatureVisitor(
      // methodData.getAccess());
      // reader.accept(trace);
      // System.err.println("Method " + name + ": " + trace.getDeclaration());
      reader.accept(methodResolver);
      if (!methodResolver.finish()) {
        return false;
      }
    } else {
      if (hasReturnType) {
        Type returnType = Type.getReturnType(methodData.getDesc());
        JType returnJType = resolveType(returnType);
        if (returnJType == null) {
          return false;
        }
        setReturnType(method, returnJType);
      }

      if (!resolveParameters(logger, method, methodData, context)) {
        return false;
      }
    }
    // The signature might not actually include the exceptions if they don't
    // include a type variable, so resolveThrows is always used (it does
    // nothing if there are already exceptions defined)
    if (!resolveThrows(method, methodData)) {
      return false;
    }
    typeParamLookup.popScope();
    return true;
  }

  private JRealClassType resolveObject(Type type) {
    assert type.getSort() == Type.OBJECT;
    String className = type.getInternalName();
    assert Name.isInternalName(className);
    JRealClassType classType = internalMapper.get(className);
    return classType;
  }

  private boolean resolvePackage(TreeLogger logger, JRealClassType type,
      List<CollectAnnotationData> annotations) {
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
    resolveAnnotations(logger, annotations, declaredAnnotations);
    addAnnotations(type.getPackage(), declaredAnnotations);
    return true;
  }

  private boolean resolveParameters(TreeLogger logger, JAbstractMethod method,
      CollectMethodData methodData, TypeOracleBuildContext context) {
    Type[] argTypes = methodData.getArgTypes();
    boolean argNamesAreReal = methodData.hasActualArgNames();
    String[] argNames = methodData.getArgNames();
    if (!argNamesAreReal) {
      String[] lookupNames = context.allMethodArgs.lookup(method, methodData);
      if (lookupNames != null) {
        argNames = lookupNames;
        argNamesAreReal = true;
      }
    }
    List<CollectAnnotationData>[] paramAnnot = methodData.getArgAnnotations();
    for (int i = 0; i < argTypes.length; ++i) {
      JType argType = resolveType(argTypes[i]);
      if (argType == null) {
        return false;
      }
      // Try to resolve annotations, ignore any that fail.
      Map<Class<? extends Annotation>, Annotation> declaredAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
      resolveAnnotations(logger, paramAnnot[i], declaredAnnotations);

      newParameter(method, argType, argNames[i], declaredAnnotations,
          argNamesAreReal);
    }
    return true;
  }

  private boolean resolveThrows(JAbstractMethod method,
      CollectMethodData methodData) {
    if (method.getThrows().length == 0) {
      for (String excName : methodData.getExceptions()) {
        JType exc = resolveType(Type.getObjectType(excName));
        if (exc == null) {
          return false;
        }
        addThrows(method, (JClassType) exc);
      }
    }
    return true;
  }

  /**
   * Returns a primitive, an array, or a JRealClassType.
   */
  private JType resolveType(Type type) {
    // Check for primitives.
    switch (type.getSort()) {
      case Type.BOOLEAN:
        return JPrimitiveType.BOOLEAN;
      case Type.BYTE:
        return JPrimitiveType.BYTE;
      case Type.CHAR:
        return JPrimitiveType.CHAR;
      case Type.SHORT:
        return JPrimitiveType.SHORT;
      case Type.INT:
        return JPrimitiveType.INT;
      case Type.LONG:
        return JPrimitiveType.LONG;
      case Type.FLOAT:
        return JPrimitiveType.FLOAT;
      case Type.DOUBLE:
        return JPrimitiveType.DOUBLE;
      case Type.VOID:
        return JPrimitiveType.VOID;
      case Type.ARRAY:
        return resolveArray(type);
      case Type.OBJECT:
        JRealClassType resolvedType = resolveObject(type);
        return possiblySubstituteRawType(resolvedType);
      default:
        assert false : "Unexpected type " + type;
        return null;
    }
  }

  /**
   * Suppress multiple validation related messages and replace with a hint.
   *
   * @param typeName fully qualified type name to check for filtering
   */
  // TODO(zundel): Can be removed when javax.validation is included in the JRE
  private boolean shouldSuppressUnresolvableAnnotation(TreeLogger logger, String typeName) {
    if (typeName.startsWith("javax.validation.")
        || typeName.startsWith("com.google.gwt.validation.")) {
      if (!warnedMissingValidationJar) {
        warnedMissingValidationJar = true;
        logger.log(TreeLogger.WARN, "Detected warnings related to '" + typeName + "'. "
            + "  Is validation-<version>.jar on the classpath?");
        logger.log(TreeLogger.INFO, "Specify -logLevel DEBUG to see all errors.");
        // Show the first error that matches
        return false;
      }
      // Suppress subsequent errors that match
      return true;
    }
    return false;
  }
}
