/*
 * 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.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.MinimalRebuildCache;
import com.google.gwt.dev.cfg.ConfigurationProperty;
import com.google.gwt.dev.cfg.Property;
import com.google.gwt.dev.javac.CompilationProblemReporter;
import com.google.gwt.dev.javac.CompilationState;
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.PrecompilationContext;
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.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.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMember;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethod.Specialization;
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.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JPermutationDependentValue;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JUnsafeTypeCoercion;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.ast.js.JDebuggerStatement;
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.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.BinaryName;
import com.google.gwt.dev.util.Name.InternalName;
import com.google.gwt.dev.util.StringInterner;
import com.google.gwt.dev.util.log.MetricName;
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 com.google.gwt.thirdparty.guava.common.base.Predicates;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.LinkedListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.thirdparty.guava.common.collect.Sets.SetView;

import java.util.Arrays;
import java.util.Collection;
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.
// TODO(stalcup): perform only binary name based lookups so that libraries
// don't need to index compilation units by both source and binary name
// TODO(stalcup): shrink the translate/flowInto graph for reference only types to eliminate
// unnecessary loading of types and increase performance.
public class UnifyAst {

  /**
   * Embodies the access methods for the compiled class, compilation unit and type for a flavor of
   * type name.
   */
  private abstract class NameBasedTypeLocator {
    private final Map<String, CompiledClass> compiledClassesByTypeName;

    private NameBasedTypeLocator(Map<String, CompiledClass> compiledClassesByTypeName) {
      this.compiledClassesByTypeName = compiledClassesByTypeName;
    }

    protected abstract boolean hasCompileErrors(String typeName);

    protected abstract void logErrorTrace(TreeLogger branch, Type logLevel, String sourceName);

    protected CompilationUnit getCompilationUnitFromSource(String typeName) {
      return compiledClassesByTypeName.get(typeName).getUnit();
    }

    protected JDeclaredType getResolvedType(String typeName) {
      JDeclaredType resolvedType = program.getFromTypeMap(typeName);
      return resolvedType;
    }

    protected boolean resolvedTypeIsAvailable(String typeName) {
      return program.getFromTypeMap(typeName) != null;
    }

    protected boolean sourceCompilationUnitIsAvailable(String typeName) {
      return compiledClassesByTypeName.containsKey(typeName);
    }
  }

  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().getUnderlyingType()));
    }

    @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) {
        refType = ((JArrayType) refType).getLeafType();
      }

      JEnumType enumType = refType.isEnumOrSubclass();
      if (enumType == null) {
        return;
      }
      for (JMethod method : enumType.getMethods()) {
        if (!method.isStatic()) {
          continue;
        }
        if (method.getSignature().startsWith("values()") ||
            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.getSourceInfo(), 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;
      }
      // Should not have an overridden type at this point.
      assert x instanceof JNewInstance || 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 JMember) {
        node = translate(x.getSourceInfo(), (JMember) 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) {
      JConstructor target = x.getTarget();
      if (target.isExternal()) {
        assert errorsFound;
        return;
      }
      flowInto(target);
    }

    @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.getSourceInfo(), 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(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(JTryStatement x, Context ctx) {
      // Needs to resolve the Exceptions Types explicitly they are multiple in Java 7 and
      // potentially different from the one in the exception variable.
      for (JTryStatement.CatchClause clause : x.getCatchClauses()) {
        List<JType> types = clause.getTypes();
        for (int i = 0; i <  types.size(); i++) {
          JReferenceType resolvedType = translate((JReferenceType) types.get(i));
          assert resolvedType.replaces(types.get(i));
          types.set(i, resolvedType);
        }
      }
    }

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

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

    @Override
    public boolean visit(JExpressionStatement x, Context ctx) {
      if (x.getExpr() instanceof JMethodCall) {
        JMethodCall call = (JMethodCall) x.getExpr();
        JMethod target = call.getTarget();
        if (GWT_DEBUGGER_METHOD_CALLS.contains(target.getQualifiedName())) {
          // We should see all calls here because GWT.debugger() returns void.
          ctx.replaceMe(new JDebuggerStatement(x.getSourceInfo()));
        }
      }
      return true;
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      currentMethod = x;
      // Only visit contents of methods defined in types which are part of this compile. Visit
      // also clinits that are reachable to make sure all the nodes that are needed for
      // propagating compile time constants are available.
      return !program.isReferenceOnly(x.getEnclosingType()) ||
          x == x.getEnclosingType().getClinitMethod();
    }

    @Override
    public boolean visit(JMethodCall x, Context ctx) {
      JMethod target = translate(x.getSourceInfo(), x.getTarget());
      x.resolve(target);
      // Special handling for magic method calls.
      JExpression replacement = maybeHandleMagicMethodCall(x);
      if (replacement != null) {
        ctx.replaceMe(accept(replacement));
        return false;
      }
      return true;
    }

    private JExpression maybeHandleMagicMethodCall(JMethodCall methodCall) {
      JExpression result;
      switch (methodCall.getTarget().getQualifiedName()) {
        case GWT_CREATE:
        case OLD_GWT_CREATE:
          result = createRebindExpression(methodCall);
          break;
        case IMPL_GET_NAME_OF:
          result = handleImplNameOf(methodCall);
          break;
        case SYSTEM_GET_PROPERTY:
        case SYSTEM_GET_PROPERTY_WITH_DEFAULT:
          result =  handleSystemGetProperty(methodCall);
          break;
        default:
          // Not a magic method call, return null so that it does not get replaced.
          return null;
      }
      if (result == null) {
        // Handled magic call possibly with an error.
        return JNullLiteral.INSTANCE;
      }
      return result;
    }

    private JExpression handleSystemGetProperty(JMethodCall gwtGetPropertyCall) {
      assert (gwtGetPropertyCall.getArgs().size() == 1 || gwtGetPropertyCall.getArgs().size() == 2);
      JExpression propertyNameExpression = gwtGetPropertyCall.getArgs().get(0);
      boolean defaultVersionCalled = gwtGetPropertyCall.getArgs().size() == 2;
      JExpression defaultValueExpression = defaultVersionCalled ?
          gwtGetPropertyCall.getArgs().get(1) : null;

      if (!(propertyNameExpression instanceof JStringLiteral)) {
        error(gwtGetPropertyCall,
            "Only string constants may be used as property name in System.getProperty()");
        return null;
      }
      String propertyName = ((JStringLiteral) propertyNameExpression).getValue();

      if (!defaultVersionCalled && !isPropertyDefined(propertyName)) {
        error(gwtGetPropertyCall, "Property '" + propertyName + "' is not defined.");
        return null;
      }

      if (isMultivaluedProperty(propertyName)) {
        error(gwtGetPropertyCall,
            "Property '" + propertyName + "' is multivalued. " +
                "Multivalued properties are not supported by System.getProperty().");
        return null;
      }

      if (defaultValueExpression != null) {
        defaultValueExpression = accept(defaultValueExpression);
      }

      return JPermutationDependentValue.createRuntimeProperty(
          program, gwtGetPropertyCall.getSourceInfo(), propertyName, defaultValueExpression);
    }

    private JExpression createRebindExpression(JMethodCall gwtCreateCall) {
      assert (gwtCreateCall.getArgs().size() == 1);
      JExpression arg = gwtCreateCall.getArgs().get(0);
      if (!(arg instanceof JClassLiteral)) {
        error(gwtCreateCall, "Only class literals may be used as arguments to GWT.create()");
        return null;
      }
      JClassLiteral classLiteral = (JClassLiteral) arg;
      if (!(classLiteral.getRefType() instanceof JDeclaredType)) {
        error(gwtCreateCall,
            "Only classes and interfaces may be used as arguments to GWT.create()");
        return null;
      }

      Event event = SpeedTracerLogger.start(CompilerEventType.VISIT_GWT_CREATE,
          "argument", classLiteral.getRefType().getName(),
          "caller", gwtCreateCall.getSourceInfo().getFileName());
      try {
        return createStaticRebindExpression(gwtCreateCall, classLiteral);
      } finally {
        event.end();
      }
    }

    private JExpression createStaticRebindExpression(JMethodCall gwtCreateCall,
        JClassLiteral classLiteral) {
      JDeclaredType type = (JDeclaredType) classLiteral.getRefType();
      String reboundTypeName = type.getName();
      // TODO(stalcup): below a MinimalRebuildCache pattern of "clear cache entries for a type" and
      // "rebuild cache entries for that type" is followed. There is a danger that a compile error
      // could occur between the two stages and leave the cache in an invalid state. Switch to a
      // transactionally safe update pattern like always updating a copy and swapping out the
      // original for the copy at the end of a successful compile.
      if (incrementalCompile) {
        // If this is the first time we've rebound this type during this compile.
        if (reboundTypeNames.add(reboundTypeName)) {
          // The rebinding of this type will accumulate rebound type to input resource associations,
          // but the accumulation should start from scratch, so clear any existing associations that
          // might have been collected in previous compiles.
          minimalRebuildCache.clearReboundTypeAssociations(reboundTypeName);
        }
        minimalRebuildCache.recordRebinderTypeForReboundType(reboundTypeName,
            currentMethod.getEnclosingType().getName());
        rebindPermutationOracle
            .getGeneratorContext().setCurrentRebindBinaryTypeName(reboundTypeName);
      }
      String requestedType = BinaryName.toSourceName(reboundTypeName);
      List<String> answers;
      try {
        answers = Lists.newArrayList(
            rebindPermutationOracle.getAllPossibleRebindAnswers(logger, requestedType));
        if (incrementalCompile) {
          // Accumulate generated artifacts so that they can be output on recompiles even if no
          // generators are run.
          ArtifactSet artifacts = rebindPermutationOracle.getGeneratorContext().getArtifacts();
          minimalRebuildCache.addGeneratedArtifacts(artifacts);
        }
        rebindPermutationOracle.getGeneratorContext().finish(logger);
        if (incrementalCompile) {
          // There may be more types known to be modified after Generator execution, which would
          // mean the previous stale types calculation was too small. Redo it.
          staleTypeNames =
              minimalRebuildCache.computeAndClearStaleTypesCache(logger, program.typeOracle);
          checkPreambleTypesStillFresh(logger);
          fullFlowIntoRemainingStaleTypes();
        }
      } catch (UnableToCompleteException e) {
        error(gwtCreateCall, "Failed to resolve '" + requestedType + "' via deferred binding");
        return null;
      }

      List<JExpression> instantiationExpressions =
          Lists.newArrayListWithCapacity(answers.size());
      for (String answer : answers) {
        JDeclaredType answerType = internalFindType(answer, sourceNameBasedTypeLocator, true);
        if (answerType == null) {
          error(gwtCreateCall, "Rebind result '" + answer + "' could not be found");
          return null;
        }
        if (!(answerType instanceof JClassType)) {
          error(gwtCreateCall, "Rebind result '" + answer + "' must be a class");
          return null;
        }
        if (answerType.isAbstract()) {
          error(gwtCreateCall, "Rebind result '" + answer + "' cannot be abstract");
          return null;
        }
        if (isJso(answerType)) {
          error(gwtCreateCall, "Rebind result '" + answer + "' cannot be a JSO");
          return null;
        }
        JExpression result = JjsUtils
            .createDefaultConstructorInstantiation(gwtCreateCall.getSourceInfo(),
                (JClassType) answerType);
        if (result == null) {
          error(gwtCreateCall,
              "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);
      }
      return JPermutationDependentValue
          .createTypeRebind(program, gwtCreateCall.getSourceInfo(), requestedType,
              answers, 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) {
        node = JsniRefLookup.findJsniRefTarget(ref, program, new JsniRefLookup.ErrorReporter() {
          @Override
          public void reportError(String errMsg) {
            error(x, errMsg);
          }
        });
      }
      if (node == null) {
        // Not found, must be null
        return null;
      }

      if (node instanceof JMethod) {
        flowInto((JMethod) node);
        program.addPinnedMethod((JMethod) node);
      }
      return new JNameOf(x.getSourceInfo(), program.getTypeJavaLangString(), (HasName) node);
    }
  }

  private boolean isMultivaluedProperty(String propertyName) {
    Property property = compilerContext.getModule().getProperties().find(propertyName);
    if (!(property instanceof ConfigurationProperty)) {
      return false;
    }

    return ((ConfigurationProperty) property).allowsMultipleValues();
  }

  private boolean isPropertyDefined(String propertyName) {
    return compilerContext.getModule().getProperties().find(propertyName) != null;
  }

  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";

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

  public static final String SYSTEM_GET_PROPERTY =
      "java.lang.System.getProperty(Ljava/lang/String;)Ljava/lang/String;";

  public static final String SYSTEM_GET_PROPERTY_WITH_DEFAULT =
      "java.lang.System.getProperty(Ljava/lang/String;Ljava/lang/String;)" +
          "Ljava/lang/String;";

  private static final String GWT_DEBUGGER_SHARED = "com.google.gwt.core.shared.GWT.debugger()V";

  private static final String GWT_DEBUGGER_CLIENT = "com.google.gwt.core.client.GWT.debugger()V";

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

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

  private static final String GWT_IS_SCRIPT = "com.google.gwt.core.shared.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;";

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

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

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

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

  /**
   * Methods for which the call site must be replaced with magic AST nodes.
   */
  private static final Set<String> GWT_DEBUGGER_METHOD_CALLS =
      Sets.newLinkedHashSet(Arrays.asList(GWT_DEBUGGER_SHARED, GWT_DEBUGGER_CLIENT));

  /**
   * Methods with magic implementations that the compiler must insert.
   */
  private final Map<String, JBooleanLiteral> replacementValueByMagicMethodQualifiedName;

  private final CompilationState compilationState;
  private final Map<String, CompiledClass> compiledClassesByInternalName;
  private final Map<String, CompiledClass> compiledClassesBySourceName;
  /**
   * JVisitor interferes with any exceptions thrown inside of a visitor traversal call tree so any
   * time UnifyAst wants to log an error and end operation care it should be done by manually
   * logging an error line and setting errorsFound to true. Adequate checking is already in place to
   * interpret this as ending further exploration and errorsFound = true is already being converted
   * to an UnableToCompleteException at the UnifyAst public function boundaries
   */
  private boolean errorsFound = false;
  private final Set<CompilationUnit> unitsWithErrorsAlreadyReported = Sets.newIdentityHashSet();

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

  private final JsProgram jsProgram;

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

  /**
   * Types which have had all of their fields and methods resolved (as opposed to the default
   * behavior of only resolving the reachable ones). Currently only used when performing per-file
   * compilation/recompilation.
   */
  private final Set<String> fullFlowTypes = Sets.newHashSet();

  private final TreeLogger logger;
  private final CompilerContext compilerContext;
  private final Map<String, JMember> resolvedMembersByQualifiedName = Maps.newHashMap();
  private final JProgram program;
  private final RebindPermutationOracle rebindPermutationOracle;
  private final Set<String> reboundTypeNames = Sets.newHashSet();

  /**
   * The names of types whose per-file compilation cached Js and StatementRanges are known to no
   * longer be valid.
   * <p>
   * Is initialized to the full initial list at the beginning of exec() and may be recalculated
   * (larger) after Generator executions reveal more modified types.
   */
  private Set<String> staleTypeNames = Sets.newHashSet();

  /**
   * The names of stale types that have been processed (fully traversed) so far.
   */
  private Set<String> processedStaleTypeNames = Sets.newHashSet();

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

  private final Set<String> liveVirtualMethods = Sets.newHashSet();
  private final Multimap<String, JMethod> pendingVirtualMethodsBySignature =
      LinkedListMultimap.create();

  private NameBasedTypeLocator sourceNameBasedTypeLocator;
  private NameBasedTypeLocator binaryNameBasedTypeLocator;
  private NameBasedTypeLocator internalNameBasedTypeLocator;

  private MinimalRebuildCache minimalRebuildCache;
  private boolean incrementalCompile;
  private final List<String> rootTypeSourceNames = Lists.newArrayList();

  public UnifyAst(TreeLogger logger, CompilerContext compilerContext, JProgram program,
      JsProgram jsProgram, PrecompilationContext precompilationContext) {

    this.incrementalCompile = compilerContext.getOptions().isIncrementalCompileEnabled();

    this.logger = logger;
    this.compilerContext = compilerContext;
    this.program = program;
    this.jsProgram = jsProgram;
    this.rebindPermutationOracle = precompilationContext.getRebindPermutationOracle();
    this.compilationState = rebindPermutationOracle.getCompilationState();
    this.compiledClassesByInternalName = compilationState.getClassFileMap();
    this.compiledClassesBySourceName = compilationState.getClassFileMapBySource();
    initializeNameBasedLocators();
    this.minimalRebuildCache = compilerContext.getMinimalRebuildCache();
    if (incrementalCompile) {
      this.staleTypeNames =
          minimalRebuildCache.computeAndClearStaleTypesCache(logger, program.typeOracle);
      checkPreambleTypesStillFresh(logger);
    }

    // Magical methods are implemented by replacing their bodies during unification.
    replacementValueByMagicMethodQualifiedName =
        ImmutableMap.<String, JBooleanLiteral>builder()
            .put(GWT_IS_CLIENT, JBooleanLiteral.TRUE)
            .put(OLD_GWT_IS_CLIENT, JBooleanLiteral.TRUE)
            .put(GWT_IS_PROD_MODE, JBooleanLiteral.TRUE)
            .put(OLD_GWT_IS_PROD_MODE, JBooleanLiteral.TRUE)
            .put(GWT_IS_SCRIPT, JBooleanLiteral.TRUE)
            .put(OLD_GWT_IS_SCRIPT, JBooleanLiteral.TRUE)
            .put(
                CLASS_DESIRED_ASSERTION_STATUS,
                JBooleanLiteral.get(compilerContext.getOptions().isEnableAssertions()))
            .put(
                CLASS_IS_CLASS_METADATA_ENABLED,
                JBooleanLiteral.get(!compilerContext.getOptions().isClassMetadataDisabled()))
            .build();
  }

  public void addRootTypes(Collection<String> rootTypeSourceNames) {
    assert this.rootTypeSourceNames.isEmpty();
    this.rootTypeSourceNames.addAll(rootTypeSourceNames);
  }

  /**
   * Special AST construction, useful for tests. Everything is resolved,
   * translated, and unified.
   */
  public void buildEverything() throws UnableToCompleteException {
    for (String internalName : compiledClassesByInternalName.keySet()) {
      String typeName = InternalName.toBinaryName(internalName);
      internalFindType(typeName, binaryNameBasedTypeLocator, true);
    }

    for (JDeclaredType type : program.getDeclaredTypes()) {
      fullFlowIntoType(type);
    }

    mainLoop();

    computeOverrides();
    if (errorsFound) {
      throw new UnableToCompleteException();
    }
    JavaAstVerifier.assertProgramIsConsistent(program);
  }

  /**
   * Translates and stitches (unifies) type ASTs into one connected graph.<br />
   *
   * Only types reachable from entry points are traversed. This speeds, saves memory trims
   * unreferenced elements.
   */
  public void exec() throws UnableToCompleteException {
    // Trace execution from entry points and resolve references.
    List<String> entryMethodNames = Lists.newArrayList();
    for (JMethod entryMethod : program.getEntryMethods()) {
      flowInto(entryMethod);
      entryMethodNames.add(entryMethod.getJsniSignature(true, true));
    }

    // Ensure that root types are loaded and possibly (depending on mode) traversed.
    List<String> rootTypeBinaryNames = Lists.newArrayList();
    for (String rootTypeSourceName : rootTypeSourceNames) {
      JDeclaredType rootType =
          internalFindType(rootTypeSourceName, sourceNameBasedTypeLocator, true);
      if (rootType == null) {
        continue;
      }
      rootTypeBinaryNames.add(rootType.getName());
      if (rootType.hasJsInteropEntryPoints()) {
        fullFlowIntoType(rootType);
      }
    }
    minimalRebuildCache.setRootTypeNames(rootTypeBinaryNames);
    minimalRebuildCache.setEntryMethodNames(entryMethodNames);

    // Some fields and methods in codegen types might only become referenced as the result of
    // visitor execution after unification. Since we don't want those fields are methods to be
    // prematurely pruned here we defensively trace them now.
    for (JClassType type : program.codeGenTypes) {
      flowInto(type);
    }

    // Make sure that the rewriting pass for the types that are represented as natives have the
    // needed members available.
    for (JDeclaredType type : program.getRepresentedAsNativeTypes()) {
      flowInto(type);
    }

    if (incrementalCompile) {
      fullFlowIntoRemainingStaleTypes();
    }

    /*
     * 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(RuntimeConstants.OBJECT_TO_STRING));
    flowInto((JMethod)
        resolvedMembersByQualifiedName.get("java.lang.String.valueOf(C)Ljava/lang/String;"));

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

    // ReplaceRunAsyncs
    if (compilerContext.getOptions().isRunAsyncEnabled()) {
      flowInto(program.getIndexedMethod(RuntimeConstants.ASYNC_FRAGMENT_LOADER_ON_LOAD));
      flowInto(program.getIndexedMethod(RuntimeConstants.ASYNC_FRAGMENT_LOADER_RUN_ASYNC));
    }

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

    mainLoop();

    if (incrementalCompile) {
      int declaredTypesInModule = program.getModuleDeclaredTypes().size();

      MetricName.DECLARED_TYPES_IN_MODULE.setAmount(logger, declaredTypesInModule);

      logger.log(TreeLogger.INFO, "Unification traversed " + liveFieldsAndMethods.size()
          + " fields and methods and " + program.getDeclaredTypes().size() + " types. "
          + declaredTypesInModule
          + " are considered part of the current module and " + fullFlowTypes.size()
          + " had all of their fields and methods traversed.");

      Set<String> remainingStaleTypeNames = computeRemainingStaleTypeNames();
      if (!remainingStaleTypeNames.isEmpty()) {
        logger.log(TreeLogger.WARN, "Some stale types (" + remainingStaleTypeNames
            + ") were not reprocessed as was expected. This is either a compiler bug or a "
            + "Generator has legitimately stopped creating these types.");
      }
      // Record the list of names of stale types that were processed, for test assertion purposes.
      minimalRebuildCache.setProcessedStaleTypeNames(fullFlowTypes);
    }

    // Compute overrides before pruning, otherwise if a parent class method is pruned an overriding
    // child class method might not look like an override.
    List<JMethod> newStubMethods = computeOverrides();

    // Make sure the created methods have the right liveness computation and don't get incorrectly
    // pruned.
    for (JMethod method : newStubMethods) {
      if (instantiatedTypes.contains(method.getEnclosingType()) &&
          liveVirtualMethods.contains(method.getSignature())) {
        liveFieldsAndMethods.add(method);
      }
    }

    if (!incrementalCompile) {
      // Post-stitching clean-ups.
      pruneDeadFieldsAndMethods();
    }
    if (errorsFound) {
      // Already logged.
      throw new UnableToCompleteException();
    }
    JavaAstVerifier.assertProgramIsConsistent(program);
  }

  /**
   * Attempts to eagerly load and traverse all remaining known-stale types.
   * <p>
   * Some types may not exist till after some Generator execution so missing types will be
   * temporarily ignored.
   */
  private void fullFlowIntoRemainingStaleTypes() {
    for (String staleTypeName : computeRemainingStaleTypeNames()) {
      JDeclaredType staleType =
          internalFindType(staleTypeName, binaryNameBasedTypeLocator, false);
      if (staleType == null) {
        // The type is Generator output and so is not usually available in the list of types
        // provided from initial JDT compilation. The staleness marking process has already
        // handled this type by cascading the staleness marking onto the types that contain the
        // GWT.create() calls that process that create this type.
        continue;
      }
      // It's possible that the type was previously loaded before it was discovered to be stale (it
      // became stale as a result of a Generator execution). If this happens then the type will have
      // already been marked "reference only" in JProgram. This needs to be undone.
      program.removeReferenceOnlyType(staleType);

      // Make sure that the entire type is traversed.
      fullFlowIntoType(staleType);
    }
  }

  private void pruneDeadFieldsAndMethods() {
    assert !incrementalCompile;
    for (JDeclaredType type : program.getDeclaredTypes()) {
      // Remove dead fields.
      for (int fieldIndex = 0; fieldIndex < type.getFields().size(); ++fieldIndex) {
        JField field = type.getFields().get(fieldIndex);
        if (!liveFieldsAndMethods.contains(field)) {
          type.removeField(fieldIndex);
          --fieldIndex;
        }
      }

      // Empty the body of dead clinits.
      JMethod clinit = type.getClinitMethod();
      if (!liveFieldsAndMethods.contains(clinit)) {
        clinit.setBody(new JMethodBody(SourceOrigin.UNKNOWN));
      }

      // Remove dead methods, but never remove clinit.
      for (int methodIndex = 1; methodIndex < type.getMethods().size(); ++methodIndex) {
        JMethod method = type.getMethods().get(methodIndex);
        // Pruning dead methods from the override list can only be done accurately in
        // non-incremental compiles because of differences in which types are loaded and thus
        // which methods are considered live.
        Iterables.removeIf(method.getOverriddenMethods(),
            Predicates.not(Predicates.in(liveFieldsAndMethods)));
        Iterables.removeIf(method.getOverridingMethods(),
            Predicates.not(Predicates.in(liveFieldsAndMethods)));
        if (!liveFieldsAndMethods.contains(method)) {
          type.removeMethod(methodIndex);
          --methodIndex;
        }
      }
    }
  }

  private void assimilateSourceUnit(CompilationUnit unit, boolean reportErrors) {
    if (unit.isError()) {
      if (reportErrors && unitsWithErrorsAlreadyReported.add(unit)) {
        CompilationProblemReporter.reportErrors(logger, unit, false);
        CompilationProblemReporter.logErrorTrace(logger, TreeLogger.ERROR,
            compilerContext, unit.getTypeName(), true);
        errorsFound = true;
      }
      return;
    }
    // Staleness calculations need to be able to trace from CompilationUnit name to the names of
    // immediately nested types. So record those associations now.
    if (incrementalCompile) {
      compilerContext.getMinimalRebuildCache().recordNestedTypeNamesPerType(unit);
    }
    // TODO(zundel): ask for a recompile if deserialization fails?
    List<JDeclaredType> types = unit.getTypes();
    assert containsAllTypes(unit, types);
    for (JDeclaredType type : types) {
      program.addType(type);
      // If we're compiling per file and we already have currently valid output for this type.
      if (incrementalCompile && !needsNewJs(type)) {
        // Then make sure we don't output new Js for this type.
        program.addReferenceOnlyType(type);
      }
    }
    for (JDeclaredType type : types) {
      resolveType(type);
      processType(type);
    }
    // When compiling per file.
    if (incrementalCompile) {
      // It's possible that a users' edits have made a type referenceable that was not previously
      // referenceable.
      for (JDeclaredType type : types) {
        // Such a type won't have any cached JS and will need a full traversal to ensure it is
        // output (the full type with all fields and methods) as new JS.
        if (needsNewJs(type)) {
          fullFlowIntoType(type);
        }
      }
    }

    for (JDeclaredType type : types) {
      /*
       * Eagerly instantiate any type that requires devirtualization, i.e. String and
       * JavaScriptObject subtypes. That way we don't have to copy the exact semantics of
       * ControlFlowAnalyzer.
       */
      if (requiresDevirtualization(type)) {
        instantiate(type);
      }

      /*
       * We also flow into the types with JsInterop entry point because our first pass on root types
       * with JsInterop entry points are missing these inner classes. For native types this ensures
       * that the constructor is considered reachable as it might be needed later for instanceof
       * and casts.
       */
      if (type.hasJsInteropEntryPoints() || type.isJsNative() || type.isJsFunction()) {
        fullFlowIntoType(type);
      }
    }
  }

  /**
   * Ensure that if any preamble types have become stale then adequate steps are taken to ensure the
   * recreation of the entire preamble chunk.
   */
  private void checkPreambleTypesStillFresh(TreeLogger logger) {
    SetView<String> stalePreambleTypes =
        Sets.intersection(staleTypeNames, minimalRebuildCache.getPreambleTypeNames());
    if (!stalePreambleTypes.isEmpty()) {
      // Stale preamble types can't be gracefully replaced. We need to clear all per-file compile
      // related caches to force a full build.
      logger.log(TreeLogger.WARN,
          "Some preamble types became stale. Recreating them is forcing a full "
          + "recompile. Stale preamble types: " + stalePreambleTypes + ".");
      minimalRebuildCache.clearPerTypeJsCache();
      staleTypeNames.clear();
      // TODO: might be able to preserve the cache of all non-stale and non-preamble types.
    }
  }

  /**
    * Compute all overrides.
    */
   private List<JMethod> computeOverrides() {
     return new ComputeOverridesAndImplementDefaultMethods().exec(program);
   }

  private Set<String> computeRemainingStaleTypeNames() {
    return Sets.newHashSet(Sets.difference(staleTypeNames, processedStaleTypeNames));
  }

  private boolean containsAllTypes(CompilationUnit unit, List<JDeclaredType> types) {
    Set<String> binaryTypeNames = Sets.newHashSet();
    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) {
    error(x.getSourceInfo(), errorMessage);
  }

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

  /**
   * Resolves all fields and methods in the given type and marks it instantiable.
   * <p>
   * The net effect is to ensure the entire type is kept and inserted into the unified AST.
   */
  private void fullFlowIntoType(JDeclaredType type) {
    String typeName = type.getName();
    if (fullFlowTypes.contains(typeName) || typeName.endsWith("package-info")) {
      return;
    }
    // The traversal of this type will accumulate rebinder type to rebound type associations, but
    // the accumulation should start from scratch, so clear any existing associations that might
    // have been collected in previous compiles.
    minimalRebuildCache.clearRebinderTypeAssociations(typeName);
    fullFlowTypes.add(typeName);
    // Remove the type from the remaining stale types set so that the fullFlowIntoStaleTypes()
    // attempt is shorter.
    processedStaleTypeNames.add(typeName);
    instantiate(type);
    flowInto(type);
  }

  private void flowInto(JDeclaredType type) {
    for (JMethod method : type.getMethods()) {
      flowInto(method);
    }
    for (JField field : type.getFields()) {
      flowInto(field);
    }
  }

  private void flowInto(JField field) {
    if (field.isExternal()) {
      assert errorsFound;
      return;
    }
    if (field == JField.NULL_FIELD) {
      return;
    }
    if (liveFieldsAndMethods.contains(field)) {
      // already flown into.
      return;
    }
    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)) {
      return;
    }

    liveFieldsAndMethods.add(method);

    method.resolve(
        translate(method.getOriginalReturnType()),
        translate(method.getOriginalParamTypes()),
        translate(method.getType()),
        translate(method.getThrownExceptions()));

    if (method.isStatic()) {
      staticInitialize(method.getEnclosingType());
    } else if (method.canBePolymorphic()) {
      String signature = method.getSignature();
      if (!liveVirtualMethods.contains(signature)) {
        liveVirtualMethods.add(signature);
        for (JMethod pendingMethod : pendingVirtualMethodsBySignature.removeAll(signature)) {
          assert instantiatedTypes.contains(pendingMethod.getEnclosingType());
          flowInto(pendingMethod);
        }
      }
    }
    resolveSpecialization(method);

    // Queue up the method to resolve the method body.
    methodsPending.add(method);
  }

  private void resolveSpecialization(JMethod method) {
    // TODO (cromwellian): Move to GwtAstBuilder eventually
    if (method.getSpecialization() == null) {
      return;
    }
    Specialization specialization = method.getSpecialization();
    if (specialization.getParams() == null) {
      logger.log(Type.ERROR, "Missing 'params' attribute at @SpecializeMethod for method "
          + method.getQualifiedName());
      errorsFound = true;
      return;
    }

    List<JType> resolvedParams = translate(specialization.getParams());

    JType resolvedReturn = translate(specialization.getReturns());

    String targetMethodSignature = JjsUtils.computeSignature(
        specialization.getTarget(), resolvedParams, resolvedReturn, false);

    JMethod targetMethod = JMethod.getExternalizedMethod(
        method.getEnclosingType().getName(), targetMethodSignature, false);
    JMethod resolvedTargetMethod = translate(method.getSourceInfo(), targetMethod);

    if (resolvedTargetMethod.isExternal()) {
      error(method.getSourceInfo(), "Unable to locate @SpecializeMethod target "
          + targetMethodSignature + " for method " + method.getQualifiedName());
      return;
    }

    flowInto(resolvedTargetMethod);
    specialization.resolve(resolvedParams, resolvedReturn, resolvedTargetMethod);
  }

  public NameBasedTypeLocator getSourceNameBasedTypeLocator() {
    return sourceNameBasedTypeLocator;
  }

  private void initializeNameBasedLocators() {
    sourceNameBasedTypeLocator = new NameBasedTypeLocator(compiledClassesBySourceName) {
      @Override
      protected boolean hasCompileErrors(String sourceName) {
        return compilerContext.getCompilationErrorsIndex().hasCompileErrors(sourceName);
      }

      @Override
      protected void logErrorTrace(TreeLogger branch, Type logLevel, String sourceName) {
        CompilationProblemReporter.logErrorTrace(branch, logLevel, compilerContext, sourceName,
            false);
      }
    };
    binaryNameBasedTypeLocator = new NameBasedTypeLocator(null) {
      @Override
      protected CompilationUnit getCompilationUnitFromSource(String binaryName) {
        // There is no binary name based index for this, use the internal name based one instead.
        return internalNameBasedTypeLocator.getCompilationUnitFromSource(
            BinaryName.toInternalName(binaryName));
      }

      @Override
      protected boolean sourceCompilationUnitIsAvailable(String binaryName) {
        // There is no binary name based index for this, use the internal name based one instead.
        return internalNameBasedTypeLocator.sourceCompilationUnitIsAvailable(
            BinaryName.toInternalName(binaryName));
      }

      @Override
      protected boolean hasCompileErrors(String binaryName) {
        return sourceNameBasedTypeLocator.hasCompileErrors(
            BinaryName.toSourceName(binaryName));
      }

      @Override
      protected void logErrorTrace(TreeLogger branch, Type logLevel, String binaryName) {
        sourceNameBasedTypeLocator.logErrorTrace(branch, logLevel,
            BinaryName.toSourceName(binaryName));
      }
    };
    internalNameBasedTypeLocator = new NameBasedTypeLocator(compiledClassesByInternalName) {
      @Override
      protected JDeclaredType getResolvedType(String internalName) {
        // There is no internal name based index for this, use the binary name based one instead.
        return binaryNameBasedTypeLocator.getResolvedType(InternalName.toBinaryName(internalName));
      }

      @Override
      protected boolean resolvedTypeIsAvailable(String internalName) {
        // There is no internal name based index for this, use the binary name based one instead.
        return binaryNameBasedTypeLocator.resolvedTypeIsAvailable(
            InternalName.toBinaryName(internalName));
      }

      @Override
      protected boolean hasCompileErrors(String internalName) {
        return sourceNameBasedTypeLocator.hasCompileErrors(
            InternalName.toSourceName(internalName));
      }

      @Override
      protected void logErrorTrace(TreeLogger branch, Type logLevel, String internalName) {
        sourceNameBasedTypeLocator.logErrorTrace(branch, logLevel,
            BinaryName.toSourceName(internalName));
      }
    };
  }

  private void instantiate(JDeclaredType type) {
    // Don't flow into all the parts of types defined outside this compile; except when the type is
    // requires devirtualization (JSOs, Strings, etc) in which case the original (non devirtualized)
    // methods may not be reachable anymore.
    if (program.isReferenceOnly(type) && !requiresDevirtualization(type)) {
      return;
    }
    if (type.isExternal()) {
      assert errorsFound;
      return;
    }

    if (instantiatedTypes.contains(type)) {
      return;
    }
    instantiatedTypes.add(type);
    if (type.getSuperClass() != null) {
      instantiate(translate(type.getSuperClass()));
    }
    for (JInterfaceType intf : type.getImplements()) {
      instantiate(translate(intf));
    }
    staticInitialize(type);

    // Flow into any reachable virtual methods.
    for (JMethod method : type.getMethods()) {
      if (method.canBeReferencedExternally()) {
        flowInto(method);
        continue;
      }
      if (!method.canBePolymorphic()) {
        continue;
      }

      String signature = method.getSignature();
      if (liveVirtualMethods.contains(signature)) {
        assert !pendingVirtualMethodsBySignature.containsKey(signature);
        flowInto(method);
      } else {
        pendingVirtualMethodsBySignature.put(signature, method);
      }
    }

    for (JField field : type.getFields()) {
      if (field.canBeReferencedExternally()) {
        flowInto(field);
      }
    }
  }

  private boolean requiresDevirtualization(JDeclaredType type) {
    // NOTE: these types are the ones {@link Devirtualizer} handles.
    return isJso(type) || type.isJsNative() ||
        // Use the version that takes names instead of instances as some
        // relevant instances might have not been leaded yet.
        JProgram.isRepresentedAsNative(type.getName());
  }

  private boolean isJso(JDeclaredType 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 (!methodsPending.isEmpty()) {
      visitor.accept(methodsPending.poll());
    }
  }

  private void processType(JDeclaredType type) {
    assert !type.isExternal();
    for (JMember member : type.getMembers()) {
      String qualifiedName = member.getQualifiedName();
      resolvedMembersByQualifiedName.put(qualifiedName, member);
      replaceMagicMethodBodies(member);
    }
  }

  private void replaceMagicMethodBodies(JMember member) {
    JExpression replacementExpression =
        replacementValueByMagicMethodQualifiedName.get(member.getQualifiedName());
    if (replacementExpression == null) {
      // Not a special method that needs replacement
      return;
    }
    JjsUtils.replaceMethodBody((JMethod) member, replacementExpression);
  }

  /**
   * During per file compilation, returns whether the given type has cached JS that can be reused.
   */
  private boolean needsNewJs(JDeclaredType type) {
    String typeName = type.getName();
    boolean hasOwnJs = minimalRebuildCache.hasJs(typeName);
    boolean isPartOfPreamble = minimalRebuildCache.getPreambleTypeNames().contains(typeName);
    return !hasOwnJs && !isPartOfPreamble;
  }

  private void resolveType(JDeclaredType type) {
    assert !type.isExternal();
    if (type.getEnclosingType() != null) {
      type.setEnclosingType(translate(type.getEnclosingType()));
    }
    if (type instanceof JClassType && type.getSuperClass() != null) {
      ((JClassType) type).setSuperClass(translate(type.getSuperClass()));
    }
    List<JInterfaceType> resolvedInterfaces = Lists.newArrayList();
    for (JInterfaceType intf : type.getImplements()) {
      resolvedInterfaces.add((JInterfaceType) translate(intf));
    }
    type.resolve(resolvedInterfaces, findPackageInfo(type));
  }

  private JDeclaredType findPackageInfo(JDeclaredType type) {
    String packagePrefix = type.getName();

    // Package prefix with trailing dot. Empty string if default package.
    packagePrefix = packagePrefix.substring(0,  packagePrefix.lastIndexOf('.') + 1);
    String pkgInfoClassName = StringInterner.get().intern(packagePrefix + "package-info");
    JDeclaredType pkgInfo = internalFindType(pkgInfoClassName, binaryNameBasedTypeLocator, false);
    // package-info classes are loaded only for their package level annotations' possible effect on
    // JsInterop configuration. They are not intended to be included in output.
    if (pkgInfo != null) {
      program.addReferenceOnlyType(pkgInfo);
    }
    return pkgInfo;
  }

  public JDeclaredType findType(String typeName, NameBasedTypeLocator nameBasedTypeLocator)
      throws UnableToCompleteException {
    JDeclaredType type = internalFindType(typeName, nameBasedTypeLocator, true);
    if (errorsFound) {
      // Already logged.
      throw new UnableToCompleteException();
    }
    return type;
  }

  private JDeclaredType internalFindType(String typeName,
      NameBasedTypeLocator nameBasedTypeLocator, boolean reportErrors) {
    if (nameBasedTypeLocator.resolvedTypeIsAvailable(typeName)) {
      // The type was already resolved.
      return nameBasedTypeLocator.getResolvedType(typeName);
    }

    if (nameBasedTypeLocator.sourceCompilationUnitIsAvailable(typeName)) {
      // Resolve from source.
      assimilateSourceUnit(nameBasedTypeLocator.getCompilationUnitFromSource(typeName),
          reportErrors);
      return nameBasedTypeLocator.getResolvedType(typeName);
    }

    if (reportErrors) {
      // The type could not be resolved as source; report the appropriate error.
      if (nameBasedTypeLocator.hasCompileErrors(typeName)) {
        TreeLogger branch = logger.branch(TreeLogger.ERROR, String.format(
            "Type %s could not be referenced because it previously failed to "
            + "compile with errors:", typeName));
        nameBasedTypeLocator.logErrorTrace(branch, TreeLogger.ERROR, typeName);
      } else {
        logger.log(TreeLogger.ERROR, String.format(
            "Could not find %s in types compiled from source. Is the source glob too strict?",
            typeName));
      }
      errorsFound = true;
    }
    return null;
  }

  private void staticInitialize(JDeclaredType type) {
    if (type.isExternal()) {
      assert errorsFound;
      return;
    }
    JMethod clinit = type.getClinitMethod();
    if (!liveFieldsAndMethods.contains(clinit)) {
      flowInto(clinit);
      if (type.getSuperClass() != null) {
        staticInitialize(translate(type.getSuperClass()));
      }
    }
  }

  /**
   * Replaces an external (stub) reference node to a particular type by the actual AST node if
   * necessary.
   */
  private <T extends JDeclaredType> T translate(T type) {
    if (!type.isExternal()) {
      return type;
    }

    T resolvedType = (T) internalFindType(type.getName(), binaryNameBasedTypeLocator, true);
    if (resolvedType == null) {
      assert errorsFound;
      return type;
    }
    assert !resolvedType.isExternal();
    return resolvedType;
  }

  /**
   * Replaces an external (stub) reference node to a particular member by the actual AST node if
   * necessary.
   */
  private <T extends JMember> T translate(SourceInfo sourceInfo, T member) {
    if (!member.isExternal()) {
      return member;
    }

    JDeclaredType enclosingType = translate(member.getEnclosingType());
    if (enclosingType.isExternal()) {
      assert errorsFound;
      return member;
    }

    String qualifiedName = member.getQualifiedName();
    T resolvedMember = (T) resolvedMembersByQualifiedName.get(qualifiedName);
    if (resolvedMember == null) {
      error(sourceInfo, "Reference to '" + qualifiedName + "' could not be resolved");
      return member;
    }

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

  /**
   * Replaces an external (stub) reference node to a particular type by the actual AST node if
   * necessary.
   */
  private JReferenceType translate(JReferenceType type) {
    JReferenceType result = type.getUnderlyingType();

    if (type instanceof JArrayType) {
      JArrayType arrayType = (JArrayType) type;
      result = program.getTypeArray(translate(arrayType.getElementType()));
    } else  if (type.isExternal()) {
      assert type instanceof JDeclaredType : "Unknown external type " + type.getName();
      result = translate((JDeclaredType) type);
    }
    assert !result.isExternal();

    if (!type.canBeNull()) {
      result = result.strengthenToNonNull();
    }

    return result;
  }

  private JType translate(JType type) {
    if (type.isPrimitiveType()) {
      return type;
    }
    return translate((JReferenceType) type);
  }

  private <T extends JType> List<T> translate(List<T> types) {
    List<T> translatedTypes = Lists.newArrayListWithCapacity(types.size());
    for (T type : types) {
      translatedTypes.add((T) translate(type));
    }
    return translatedTypes;
  }
}
