/*
 * Copyright 2011 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.jjs.impl;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.javac.CompilationProblemReporter;
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.javac.CompiledClass;
import com.google.gwt.dev.jdt.RebindPermutationOracle;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.JJSOptions;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConditional;
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JEnumType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JGwtCreate;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNameOf;
import com.google.gwt.dev.jjs.ast.JNewArray;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JNonNullType;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import com.google.gwt.dev.jjs.ast.js.JsonArray;
import com.google.gwt.dev.jjs.ast.js.JsonObject;
import com.google.gwt.dev.js.ast.JsNestingScope;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.util.JsniRef;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Name.BinaryName;
import com.google.gwt.dev.util.Name.InternalName;
import com.google.gwt.dev.util.collect.IdentityHashSet;
import com.google.gwt.dev.util.collect.Lists;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

/**
 * Take independently-compiled types and merge them into a single AST.
 * 
 * Works kind of like {@link ControlFlowAnalyzer} in terms of reachability,
 * except that in some cases it's easier to be conservative and visit relatively
 * more nodes than CFA would.
 * 
 * Operates based on a work-queue to prevent recursion sickness.
 * 
 * Must handle:
 * 
 * - Type reference resolution
 * 
 * - Field and method reference resolution
 * 
 * - General code flow like ControlFlowAnalyzer
 * 
 * - GWT.create(), GWT.runAsync(), Impl.getNameOf()
 * 
 * - Stitch native methods into JsProgram
 * 
 * - Class.desiredAssertionStatus, Class.isClassMetaDataEnabled, GWT.isClient,
 * GWT.isProdMode, GWT.isScript.
 * 
 * TODO: SOYC correlations.
 */
public class UnifyAst {

  private class UnifyVisitor extends JModVisitor {

    private JMethod currentMethod;

    @Override
    public void endVisit(JArrayType x, Context ctx) {
      assert false : "Should not get here";
    }

    @Override
    public void endVisit(JBinaryOperation x, Context ctx) {
      // Concat ops need to resolve string type.
      x.setType(translate(x.getType()));
    }

    @Override
    public void endVisit(JCastOperation x, Context ctx) {
      x.resolve(translate(x.getCastType()));
    }

    @Override
    public void endVisit(JClassLiteral x, Context ctx) {
      JType refType = translate(x.getRefType());
      x.resolve(refType);

      // ImplementClassLiteralsAsFields: rescue enumType.values()/valueOf().
      if (refType instanceof JArrayType) {
        JType leafType = ((JArrayType) refType).getLeafType();
        if (leafType instanceof JReferenceType) {
          refType = leafType;
        }
      }
      if (refType instanceof JClassType) {
        JClassType classType = (JClassType) refType;
        JEnumType enumType = classType.isEnumOrSubclass();
        if (enumType != null) {
          for (JMethod method : enumType.getMethods()) {
            if (method.isStatic()) {
              if (method.getSignature().startsWith("values()")) {
                flowInto(method);
              } else if (method.getSignature().startsWith("valueOf(Ljava/lang/String;)")) {
                flowInto(method);
              }
            }
          }
        }
      }
    }

    @Override
    public void endVisit(JClassType x, Context ctx) {
      assert false : "Should not get here";
    }

    @Override
    public void endVisit(JConditional x, Context ctx) {
      x.setType(translate(x.getType()));
    }

    @Override
    public void endVisit(JConstructor x, Context ctx) {
      // Process as method.
      super.endVisit(x, ctx);
      instantiate(x.getEnclosingType());
    }

    @Override
    public void endVisit(JDeclaredType x, Context ctx) {
      assert false : "Should not get here";
    }

    @Override
    public void endVisit(JExpression x, Context ctx) {
      assert !x.getType().isExternal() || errorsFound;
    }

    @Override
    public void endVisit(JField x, Context ctx) {
      assert false : "Should not get here";
    }

    @Override
    public void endVisit(JFieldRef x, Context ctx) {
      JField field = translate(x.getField());
      flowInto(field);
      x.resolve(field);
      // Should not have an overridden type at this point.
      assert x.getType() == x.getField().getType();
      assert !x.getEnclosingType().isExternal();
    }

    @Override
    public void endVisit(JInstanceOf x, Context ctx) {
      x.resolve(translate(x.getTestType()));
    }

    @Override
    public void endVisit(JInterfaceType x, Context ctx) {
      assert false : "Should not get here";
    }

    @Override
    public void endVisit(JMethod x, Context ctx) {
      currentMethod = null;
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      // Already resolved during visit().
      JMethod target = x.getTarget();
      if (target.isExternal()) {
        assert errorsFound;
        return;
      }
      if (magicMethodCalls.contains(target)) {
        JExpression result = handleMagicMethodCall(x);
        if (result == null) {
          // Error of some sort.
          result = JNullLiteral.INSTANCE;
        }
        result = this.accept(result);
        ctx.replaceMe(result);
        return;
      }
      if (!(x instanceof JNewInstance)) {
        // Should not have an overridden type at this point.
        assert x.getType() == target.getType();
      }
      flowInto(target);
    }

    @Override
    public void endVisit(JNameOf x, Context ctx) {
      HasName node = x.getNode();
      if (node instanceof JType) {
        node = translate((JType) node);
      } else if (node instanceof JField) {
        node = translate((JField) node);
      } else if (node instanceof JMethod) {
        node = translate((JMethod) node);
      } else {
        assert false : "Should not get here";
      }
      x.resolve(node, (JClassType) translate(x.getType().getUnderlyingType()));
    }

    @Override
    public void endVisit(JNewArray x, Context ctx) {
      x.setType((JArrayType) translate(x.getArrayType()));
    }

    @Override
    public void endVisit(JNewInstance x, Context ctx) {
      flowInto(x.getTarget());
      assert !x.getEnclosingType().isExternal();
    }

    @Override
    public void endVisit(JsniFieldRef x, Context ctx) {
      endVisit((JFieldRef) x, ctx);
    }

    @Override
    public void endVisit(JsniMethodBody x, Context ctx) {
      JsNestingScope funcScope = (JsNestingScope) x.getFunc().getScope();
      assert funcScope.getParent() == JsRootScope.INSTANCE;
      funcScope.nestInto(jsProgram.getScope());
    }

    @Override
    public void endVisit(JsniMethodRef x, Context ctx) {
      JMethod target = translate(x.getTarget());
      x.resolve(target, program.getJavaScriptObject());
      flowInto(target);
    }

    @Override
    public void endVisit(JsonArray x, Context ctx) {
      x.resolve(translate(x.getType()));
    }

    @Override
    public void endVisit(JsonObject x, Context ctx) {
      x.resolve(translate(x.getType()));
    }

    @Override
    public void endVisit(JStringLiteral x, Context ctx) {
      JClassType stringType = program.getTypeJavaLangString();
      x.resolve(stringType);
      instantiate(stringType);
    }

    @Override
    public void endVisit(JThisRef x, Context ctx) {
      assert !x.getType().isExternal();
    }

    @Override
    public void endVisit(JVariable x, Context ctx) {
      x.setType(translate(x.getType()));
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      currentMethod = x;
      return true;
    }

    @Override
    public boolean visit(JMethodCall x, Context ctx) {
      JMethod target = translate(x.getTarget());
      x.resolve(target);
      // Special handling.
      return !magicMethodCalls.contains(target);
    }

    private JExpression handleGwtCreate(JMethodCall x) {
      assert (x.getArgs().size() == 1);
      JExpression arg = x.getArgs().get(0);
      if (!(arg instanceof JClassLiteral)) {
        error(x, "Only class literals may be used as arguments to GWT.create()");
        return null;
      }
      JClassLiteral classLiteral = (JClassLiteral) arg;
      if (!(classLiteral.getRefType() instanceof JDeclaredType)) {
        error(x, "Only classes and interfaces may be used as arguments to GWT.create()");
        return null;
      }
      JDeclaredType type = (JDeclaredType) classLiteral.getRefType();
      String reqType = JGwtCreate.nameOf(type);
      List<String> answers;
      try {
        answers = Lists.create(rpo.getAllPossibleRebindAnswers(logger, reqType));
        rpo.getGeneratorContext().finish(logger);
      } catch (UnableToCompleteException e) {
        error(x, "Failed to resolve '" + reqType + "' via deferred binding");
        return null;
      }

      ArrayList<JExpression> instantiationExpressions = new ArrayList<JExpression>(answers.size());
      for (String answer : answers) {
        JDeclaredType answerType = searchForTypeBySource(answer);
        if (answerType == null) {
          error(x, "Rebind result '" + answer + "' could not be found");
          return null;
        }
        if (!(answerType instanceof JClassType)) {
          error(x, "Rebind result '" + answer + "' must be a class");
          return null;
        }
        if (answerType.isAbstract()) {
          error(x, "Rebind result '" + answer + "' cannot be abstract");
          return null;
        }
        JExpression result =
            JGwtCreate.createInstantiationExpression(x.getSourceInfo(), (JClassType) answerType,
                currentMethod.getEnclosingType());
        if (result == null) {
          error(x, "Rebind result '" + answer + "' has no default (zero argument) constructors");
          return null;
        }
        instantiationExpressions.add(result);
      }
      assert answers.size() == instantiationExpressions.size();
      if (answers.size() == 1) {
        return instantiationExpressions.get(0);
      } else {
        return new JGwtCreate(x.getSourceInfo(), reqType, answers, program.getTypeJavaLangObject(),
            instantiationExpressions);
      }
    }

    private JExpression handleImplNameOf(final JMethodCall x) {
      assert (x.getArgs().size() == 1);
      JExpression arg = x.getArgs().get(0);
      if (!(arg instanceof JStringLiteral)) {
        error(x, "Only string literals may be used as arguments to Impl.getNameOf()");
        return null;
      }
      JStringLiteral stringLiteral = (JStringLiteral) arg;
      String stringValue = stringLiteral.getValue();
      JNode node = null;

      JsniRef ref = JsniRef.parse(stringValue);
      if (ref != null) {
        if (Name.isBinaryName(ref.className())) {
          searchForTypeByBinary(ref.className());
        }
        node = JsniRefLookup.findJsniRefTarget(ref, program, new JsniRefLookup.ErrorReporter() {
          public void reportError(String errMsg) {
            error(x, errMsg);
          }
        });
      } else {
        // See if it's just @foo.Bar, which would result in the class seed
        String typeName = stringValue.charAt(0) == '@' ? stringValue.substring(1) : stringValue;
        node = searchForTypeByBinary(typeName);
      }
      if (node == null) {
        // Not found, must be null
        return null;
      } else {
        return new JNameOf(x.getSourceInfo(), program.getTypeJavaLangString(), (HasName) node);
      }
    }

    private JExpression handleMagicMethodCall(JMethodCall x) {
      JMethod target = x.getTarget();
      String sig = target.getEnclosingType().getName() + '.' + target.getSignature();
      if (GWT_CREATE.equals(sig)) {
        return handleGwtCreate(x);
      } else if (IMPL_GET_NAME_OF.equals(sig)) {
        return handleImplNameOf(x);
      }
      throw new InternalCompilerException("Unknown magic method");
    }
  }

  private static final String CLASS_DESIRED_ASSERTION_STATUS =
      "java.lang.Class.desiredAssertionStatus()Z";

  private static final String CLASS_IS_CLASS_METADATA_ENABLED =
      "java.lang.Class.isClassMetadataEnabled()Z";

  private static final String GWT_CREATE =
      "com.google.gwt.core.client.GWT.create(Ljava/lang/Class;)Ljava/lang/Object;";

  private static final String GWT_IS_CLIENT = "com.google.gwt.core.client.GWT.isClient()Z";

  private static final String GWT_IS_PROD_MODE = "com.google.gwt.core.client.GWT.isProdMode()Z";

  private static final String GWT_IS_SCRIPT = "com.google.gwt.core.client.GWT.isScript()Z";

  private static final String IMPL_GET_NAME_OF =
      "com.google.gwt.core.client.impl.Impl.getNameOf(Ljava/lang/String;)Ljava/lang/String;";

  /**
   * Methods for which the call site must be replaced with magic AST nodes.
   */
  private static final Set<String> MAGIC_METHOD_CALLS = new LinkedHashSet<String>(Arrays.asList(
      GWT_CREATE, IMPL_GET_NAME_OF));

  /**
   * Methods with magic implementations that the compiler must insert.
   */
  private static final Set<String> MAGIC_METHOD_IMPLS = new LinkedHashSet<String>(Arrays.asList(
      GWT_IS_CLIENT, GWT_IS_PROD_MODE, GWT_IS_SCRIPT, CLASS_DESIRED_ASSERTION_STATUS,
      CLASS_IS_CLASS_METADATA_ENABLED));

  private final Map<String, CompiledClass> classFileMap;
  private final Map<String, CompiledClass> classFileMapBySource;
  private boolean errorsFound = false;
  private final Set<CompilationUnit> failedUnits = new IdentityHashSet<CompilationUnit>();
  private final Map<String, JField> fieldMap = new HashMap<String, JField>();

  /**
   * The set of types currently known to be instantiable. Like
   * {@link ControlFlowAnalyzer#instantiatedTypes}.
   */
  private final Set<JDeclaredType> instantiatedTypes = new IdentityHashSet<JDeclaredType>();

  private final JsProgram jsProgram;

  /**
   * Fields and methods that are referenceable. Like
   * {@link ControlFlowAnalyzer#liveFieldsAndMethods}.
   */
  private final Set<JNode> liveFieldsAndMethods = new IdentityHashSet<JNode>();

  private TreeLogger logger;
  private Set<JMethod> magicMethodCalls = new IdentityHashSet<JMethod>();
  private final Map<String, JMethod> methodMap = new HashMap<String, JMethod>();
  private final JJSOptions options;
  private final JProgram program;
  private final RebindPermutationOracle rpo;

  /**
   * A work queue of methods whose bodies we need to traverse. Prevents
   * excessive stack use.
   */
  private final Queue<JMethod> todo = new LinkedList<JMethod>();

  private final Set<String> virtualMethodsLive = new HashSet<String>();
  private final Map<String, List<JMethod>> virtualMethodsPending =
      new java.util.HashMap<String, List<JMethod>>();

  public UnifyAst(JProgram program, JsProgram jsProgram, JJSOptions options,
      RebindPermutationOracle rpo) {
    this.program = program;
    this.jsProgram = jsProgram;
    this.options = options;
    this.rpo = rpo;
    this.classFileMap = rpo.getCompilationState().getClassFileMap();
    this.classFileMapBySource = rpo.getCompilationState().getClassFileMapBySource();
  }

  public void addRootTypes(Collection<String> sourceTypeNames) {
    for (String sourceTypeName : sourceTypeNames) {
      searchForTypeBySource(sourceTypeName);
    }
  }

  /**
   * Special AST construction, useful for tests. Everything is resolved,
   * translated, and unified.
   */
  public void buildEverything(TreeLogger logger) throws UnableToCompleteException {
    this.logger = logger;
    for (String internalName : classFileMap.keySet()) {
      String typeName = InternalName.toBinaryName(internalName);
      searchForTypeByBinary(typeName);
    }

    for (JDeclaredType type : program.getDeclaredTypes()) {
      instantiate(type);
      for (JField field : type.getFields()) {
        flowInto(field);
      }
      for (JMethod method : type.getMethods()) {
        flowInto(method);
      }
    }

    mainLoop();

    computeOverrides();
    if (errorsFound) {
      throw new UnableToCompleteException();
    }
  }

  /**
   * For normal compilation, only translate and stitch types reachable from
   * entry points. This reduces memory and improves compile speed. Any
   * unreachable elements are pruned.
   */
  public void exec(TreeLogger logger) throws UnableToCompleteException {
    this.logger = logger;

    // Trace execution from entry points.
    for (JMethod entryMethod : program.getEntryMethods()) {
      flowInto(entryMethod);
    }

    // Trace execution from compiler code gen types.
    for (JClassType type : program.codeGenTypes) {
      for (JMethod method : type.getMethods()) {
        flowInto(method);
      }
    }

    /*
     * Since we're not actually optimizing here, it's easier to just visit
     * certain things up front instead of duplicating the exacting semantics of
     * ControlFlowAnalyzer.
     */
    // String literals.
    instantiate(program.getTypeJavaLangString());
    // ControlFlowAnalyzer.rescueByConcat().
    flowInto(program.getIndexedMethod("Object.toString"));
    mapApi(program.getTypeJavaLangString());
    flowInto(methodMap.get("java.lang.String.valueOf(C)Ljava/lang/String;"));

    // Additional pre-optimization code gen.
    // TODO: roll these into this class?

    // EnumNameObfuscator
    flowInto(program.getIndexedMethod("Enum.obfuscatedName"));

    // FixAssignmentToUnbox
    AutoboxUtils autoboxUtils = new AutoboxUtils(program);
    for (JMethod method : autoboxUtils.getBoxMethods()) {
      flowInto(method);
    }
    for (JMethod method : autoboxUtils.getUnboxMethods()) {
      flowInto(method);
    }

    // ReplaceRunAsyncs
    if (options.isRunAsyncEnabled()) {
      flowInto(program.getIndexedMethod("AsyncFragmentLoader.onLoad"));
      flowInto(program.getIndexedMethod("AsyncFragmentLoader.runAsync"));
    }

    // ImplementClassLiteralsAsFields
    staticInitialize(program.getTypeClassLiteralHolder());
    for (JMethod method : program.getTypeJavaLangClass().getMethods()) {
      if (method.isStatic() && method.getName().startsWith("createFor")) {
        flowInto(method);
      }
    }

    mainLoop();

    // Post-stitching clean-ups.

    // Prune any untranslated types, fields, and methods.
    for (Iterator<JDeclaredType> it = program.getDeclaredTypes().iterator(); it.hasNext();) {
      JDeclaredType type = it.next();
      boolean isInstantiated = instantiatedTypes.contains(type);
      for (int i = 0; i < type.getFields().size(); ++i) {
        JField field = type.getFields().get(i);
        if (!liveFieldsAndMethods.contains(field) || (!field.isStatic() && !isInstantiated)) {
          type.removeField(i);
          --i;
        }
      }

      // Special clinit handling.
      JMethod clinit = type.getMethods().get(0);
      if (!liveFieldsAndMethods.contains(clinit)) {
        clinit.setBody(new JMethodBody(SourceOrigin.UNKNOWN));
      }
      for (int i = 1; i < type.getMethods().size(); ++i) {
        JMethod method = type.getMethods().get(i);
        if (!liveFieldsAndMethods.contains(method) || (!method.isStatic() && !isInstantiated)) {
          type.removeMethod(i);
          --i;
        }
      }
    }

    computeOverrides();
    if (errorsFound) {
      throw new UnableToCompleteException();
    }
  }

  private void assimilateUnit(CompilationUnit unit) {
    if (unit.isError()) {
      if (failedUnits.add(unit)) {
        CompilationProblemReporter.reportErrors(logger, unit, false);
        errorsFound = true;
      }
      return;
    }
    // TODO(zundel): ask for a recompile if deserialization fails?
    List<JDeclaredType> types = unit.getTypes();
    assert containsAllTypes(unit, types);
    for (JDeclaredType t : types) {
      program.addType(t);
    }
    for (JDeclaredType t : types) {
      resolveType(t);
    }
    /*
     * Eagerly instantiate any JavaScriptObject subtypes. That way we don't have
     * to copy the exact semantics of ControlFlowAnalyzer.
     */
    for (JDeclaredType t : types) {
      if (t instanceof JClassType && isJso((JClassType) t)) {
        instantiate(t);
      }
    }
  }

  private void collectUpRefs(JDeclaredType type, Map<String, Set<JMethod>> collected) {
    if (type == null) {
      return;
    }
    for (JMethod method : type.getMethods()) {
      if (method.canBePolymorphic()) {
        Set<JMethod> set = collected.get(method.getSignature());
        if (set != null) {
          set.add(method);
        }
      }
    }
    collectUpRefsInSupers(type, collected);
  }

  private void collectUpRefsInSupers(JDeclaredType type, Map<String, Set<JMethod>> collected) {
    collectUpRefs(type.getSuperClass(), collected);
    for (JInterfaceType intfType : type.getImplements()) {
      collectUpRefs(intfType, collected);
    }
  }

  /**
   * Compute all overrides.
   */
  private void computeOverrides() {
    for (JDeclaredType type : program.getDeclaredTypes()) {
      Map<String, Set<JMethod>> collected = new HashMap<String, Set<JMethod>>();
      for (JMethod method : type.getMethods()) {
        if (method.canBePolymorphic()) {
          collected.put(method.getSignature(), new LinkedHashSet<JMethod>());
        }
      }
      collectUpRefsInSupers(type, collected);
      for (JMethod method : type.getMethods()) {
        if (method.canBePolymorphic()) {
          Set<JMethod> uprefs = collected.get(method.getSignature());
          method.addOverrides(Lists.create(uprefs));
        }
      }
    }
  }

  private boolean containsAllTypes(CompilationUnit unit, List<JDeclaredType> types) {
    Set<String> binaryTypeNames = new HashSet<String>();
    for (JDeclaredType type : types) {
      binaryTypeNames.add(type.getName());
    }
    for (CompiledClass cc : unit.getCompiledClasses()) {
      if (!binaryTypeNames.contains(InternalName.toBinaryName(cc.getInternalName()))) {
        return false;
      }
    }
    return true;
  }

  private void error(JNode x, String errorMessage) {
    errorsFound = true;
    TreeLogger branch =
        logger
            .branch(TreeLogger.ERROR, "Errors in '" + x.getSourceInfo().getFileName() + "'", null);
    // Append 'Line #: msg' to the error message.
    StringBuffer msgBuf = new StringBuffer();
    int line = x.getSourceInfo().getStartLine();
    if (line > 0) {
      msgBuf.append("Line ");
      msgBuf.append(line);
      msgBuf.append(": ");
    }
    msgBuf.append(errorMessage);
    branch.log(TreeLogger.ERROR, msgBuf.toString());
  }

  private void flowInto(JField field) {
    if (field.isExternal()) {
      assert errorsFound;
      return;
    }
    if (field == JField.NULL_FIELD) {
      return;
    }
    if (!liveFieldsAndMethods.contains(field)) {
      liveFieldsAndMethods.add(field);
      field.setType(translate(field.getType()));
      if (field.isStatic()) {
        staticInitialize(field.getEnclosingType());
      }
    }
  }

  private void flowInto(JMethod method) {
    if (method.isExternal()) {
      assert errorsFound;
      return;
    }
    if (method == JMethod.NULL_METHOD) {
      return;
    }
    if (!liveFieldsAndMethods.contains(method)) {
      liveFieldsAndMethods.add(method);
      JType originalReturnType = translate(method.getOriginalReturnType());
      List<JType> originalParamTypes = new ArrayList<JType>(method.getOriginalParamTypes().size());
      for (JType originalParamType : method.getOriginalParamTypes()) {
        originalParamTypes.add(translate(originalParamType));
      }
      JType returnType = translate(method.getType());
      List<JClassType> thrownExceptions =
          new ArrayList<JClassType>(method.getThrownExceptions().size());
      for (JClassType thrownException : method.getThrownExceptions()) {
        thrownExceptions.add(translate(thrownException));
      }
      method.resolve(originalReturnType, originalParamTypes, returnType, thrownExceptions);
      if (method.isStatic()) {
        staticInitialize(method.getEnclosingType());
      } else if (method.canBePolymorphic()) {
        String signature = method.getSignature();
        if (!virtualMethodsLive.contains(signature)) {
          virtualMethodsLive.add(signature);
          List<JMethod> pending = virtualMethodsPending.remove(signature);
          if (pending != null) {
            for (JMethod p : pending) {
              assert instantiatedTypes.contains(p.getEnclosingType());
              flowInto(p);
            }
          }
        }
      }
      // Queue up visit / resolve on the body.
      todo.add(method);
    }
  }

  private void implementMagicMethod(JMethod method, JExpression returnValue) {
    JMethodBody body = (JMethodBody) method.getBody();
    JBlock block = body.getBlock();
    SourceInfo info;
    if (block.getStatements().size() > 0) {
      info = block.getStatements().get(0).getSourceInfo();
    } else {
      info = method.getSourceInfo();
    }
    block.clear();
    block.addStmt(new JReturnStatement(info, returnValue));
  }

  private void instantiate(JDeclaredType type) {
    if (type.isExternal()) {
      assert errorsFound;
      return;
    }
    if (!instantiatedTypes.contains(type)) {
      instantiatedTypes.add(type);
      if (type.getSuperClass() != null) {
        instantiate(type.getSuperClass());
      }
      for (JInterfaceType intf : type.getImplements()) {
        instantiate(intf);
      }
      staticInitialize(type);

      // Flow into any reachable virtual methods.
      for (JMethod method : type.getMethods()) {
        if (method.canBePolymorphic()) {
          String signature = method.getSignature();
          if (virtualMethodsLive.contains(signature)) {
            assert !virtualMethodsPending.containsKey(signature);
            flowInto(method);
          } else {
            List<JMethod> pending = virtualMethodsPending.get(signature);
            if (pending == null) {
              pending = Lists.create(method);
            } else {
              pending = Lists.add(pending, method);
            }
            virtualMethodsPending.put(signature, pending);
          }
        }
      }
    }
  }

  private boolean isJso(JClassType type) {
    if (type == null) {
      return false;
    }
    return type == program.getJavaScriptObject() || isJso(type.getSuperClass());
  }

  /**
   * Main loop: run through the queue doing deferred resolution. We could have
   * made this entirely recursive, but a work queue uses much less max stack.
   */
  private void mainLoop() {
    UnifyVisitor visitor = new UnifyVisitor();
    while (!todo.isEmpty()) {
      visitor.accept(todo.poll());
    }
  }

  private void mapApi(JDeclaredType type) {
    assert !type.isExternal();
    for (JField field : type.getFields()) {
      String sig = type.getName() + '.' + field.getSignature();
      fieldMap.put(sig, field);
    }
    for (JMethod method : type.getMethods()) {
      String sig = type.getName() + '.' + method.getSignature();
      methodMap.put(sig, method);
      if (MAGIC_METHOD_CALLS.contains(sig)) {
        magicMethodCalls.add(method);
      }
      if (MAGIC_METHOD_IMPLS.contains(sig)) {
        if (sig.startsWith("com.google.gwt.core.client.GWT.")) {
          // GWT.isClient, GWT.isScript, GWT.isProdMode all true.
          implementMagicMethod(method, JBooleanLiteral.TRUE);
        } else {
          assert sig.startsWith("java.lang.Class.");
          if (CLASS_DESIRED_ASSERTION_STATUS.equals(sig)) {
            implementMagicMethod(method, JBooleanLiteral.get(options.isEnableAssertions()));
          } else if (CLASS_IS_CLASS_METADATA_ENABLED.equals(sig)) {
            implementMagicMethod(method, JBooleanLiteral.get(!options.isClassMetadataDisabled()));
          } else {
            assert false;
          }
        }
      }
    }
  }

  private void resolveType(JDeclaredType type) {
    assert !type.isExternal();
    if (type instanceof JClassType && type.getSuperClass() != null) {
      ((JClassType) type).setSuperClass(translate(type.getSuperClass()));
    }
    List<JInterfaceType> resolvedInterfaces = new ArrayList<JInterfaceType>();
    for (JInterfaceType intf : type.getImplements()) {
      resolvedInterfaces.add((JInterfaceType) translate(intf));
    }
    List<JNode> resolvedRescues = new ArrayList<JNode>();
    for (JNode node : type.getArtificialRescues()) {
      if (node instanceof JType) {
        node = translate((JType) node);
      } else if (node instanceof JField) {
        node = translate((JField) node);
      } else if (node instanceof JMethod) {
        node = translate((JMethod) node);
      } else {
        assert false : "Unknown artificial rescue node.";
      }
      resolvedRescues.add(node);
    }
    type.resolve(resolvedInterfaces, resolvedRescues);
  }

  private JDeclaredType searchForTypeByBinary(String binaryTypeName) {
    JDeclaredType type = program.getFromTypeMap(binaryTypeName);
    if (type == null) {
      CompiledClass cc = classFileMap.get(BinaryName.toInternalName(binaryTypeName));
      if (cc == null) {
        // TODO: error
        throw new NoClassDefFoundError(binaryTypeName);
      }
      assimilateUnit(cc.getUnit());
      type = program.getFromTypeMap(binaryTypeName);
      assert type != null || errorsFound;
    }
    return type;
  }

  private JDeclaredType searchForTypeBySource(String sourceTypeName) {
    JDeclaredType type = program.getFromTypeMap(sourceTypeName);
    if (type == null) {
      CompiledClass cc = classFileMapBySource.get(sourceTypeName);
      if (cc == null) {
        // TODO: error
        throw new NoClassDefFoundError(sourceTypeName);
      }
      assimilateUnit(cc.getUnit());
      type = program.getFromTypeMap(sourceTypeName);
      assert type != null || errorsFound;
    }
    return type;
  }

  private void staticInitialize(JDeclaredType type) {
    if (type.isExternal()) {
      assert errorsFound;
      return;
    }
    JMethod clinit = type.getMethods().get(0);
    if (!liveFieldsAndMethods.contains(clinit)) {
      flowInto(clinit);
      if (type.getSuperClass() != null) {
        staticInitialize(type.getSuperClass());
      }
      for (JNode node : type.getArtificialRescues()) {
        if (node instanceof JType) {
          if (node instanceof JDeclaredType) {
            instantiate((JDeclaredType) node);
          }
        } else if (node instanceof JField) {
          JField field = (JField) node;
          flowInto(field);
          if (!field.isFinal()) {
            field.setVolatile();
          }
        } else if (node instanceof JMethod) {
          flowInto((JMethod) node);
        } else {
          assert false : "Unknown artificial rescue node.";
        }
      }
    }
  }

  private JClassType translate(JClassType type) {
    return (JClassType) translate((JDeclaredType) type);
  }

  private JDeclaredType translate(JDeclaredType type) {
    if (!type.isExternal()) {
      return type;
    }

    String typeName = type.getName();
    JDeclaredType newType = searchForTypeByBinary(typeName);
    if (newType == null) {
      assert errorsFound;
      return type;
    }

    assert !newType.isExternal();
    return newType;
  }

  private JField translate(JField field) {
    if (!field.isExternal()) {
      return field;
    }

    JDeclaredType enclosingType = field.getEnclosingType();
    String sig = enclosingType.getName() + '.' + field.getSignature();
    JField newField = fieldMap.get(sig);
    if (newField != null) {
      return newField;
    }

    enclosingType = translate(enclosingType);
    if (enclosingType.isExternal()) {
      assert errorsFound;
      return field;
    }
    mapApi(enclosingType);

    // Now the field should be there.
    field = fieldMap.get(sig);
    if (field == null) {
      // TODO: error logging
      throw new NoSuchFieldError(sig);
    }

    assert !field.isExternal();
    return field;
  }

  private JMethod translate(JMethod method) {
    if (!method.isExternal()) {
      return method;
    }

    JDeclaredType enclosingType = method.getEnclosingType();
    String sig = enclosingType.getName() + '.' + method.getSignature();
    JMethod newMethod = methodMap.get(sig);
    if (newMethod != null) {
      return newMethod;
    }

    enclosingType = translate(enclosingType);
    if (enclosingType.isExternal()) {
      assert errorsFound;
      return method;
    }
    mapApi(enclosingType);

    // Now the method should be there.
    method = methodMap.get(sig);
    if (method == null) {
      // TODO: error logging
      throw new NoSuchMethodError(sig);
    }
    assert !method.isExternal();
    return method;
  }

  private JReferenceType translate(JReferenceType type) {
    if (type instanceof JArrayType) {
      JArrayType arrayType = (JArrayType) type;
      type = program.getTypeArray(translate(arrayType.getElementType()));
    } else if (type.isExternal()) {
      if (type instanceof JDeclaredType) {
        type = translate((JDeclaredType) type);
      } else if (type instanceof JNonNullType) {
        type = translate(type.getUnderlyingType()).getNonNull();
      } else {
        assert false : "Unknown external type";
      }
    }
    assert !type.isExternal();
    return type;
  }

  private JType translate(JType type) {
    if (type instanceof JPrimitiveType) {
      return type;
    }
    return translate((JReferenceType) type);
  }
}
