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

import com.google.gwt.dev.javac.JsniCollector;
import com.google.gwt.dev.jdt.AbstractCompiler.CompilationResults;
import com.google.gwt.dev.jdt.SafeASTVisitor;
import com.google.gwt.dev.jjs.HasSourceInfo;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.JClassType;
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.JField;
import com.google.gwt.dev.jjs.ast.JField.Disposition;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JNullType;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.js.JsAbstractSymbolResolver;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNode;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsProgram;
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 org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.util.Util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * This is a Builder for {@link TypeMap}. The whole point of this pass is to
 * create raw unfinished, unlinked AST nodes for types, methods, fields, and
 * parameters, and to map the original JDT nodes to these AST nodes. That way
 * when GenerateJavaDom runs, it just uses the TypeMap output from this Builder
 * to retrieve whatever referenceable nodes it needs without worrying about
 * whether they need to be created. Building our AST from JDT starts here.
 */
public class BuildTypeMap {

  /**
   * Creates JNodes for every method, field, initializer, parameter, and local
   * and memorizes the mapping from the JDT Binding to the corresponding JNode
   * for each thing created. Note that this pass also 1) sets up the super
   * type(s) for any member or local types created in BuildTypeMapVisitor (see
   * the comments there about why it had to be deferred). 2) adds each
   * user-defined type to a flat list. 3) Creates JNodes for all methods and
   * variables and memorizes the mapping from the JDT Binding to the
   * corresponding JNode for each created method and variable. 4) Maps all
   * synthetic arguments and fields for nested and local classes. 5) Slurps in
   * JSNI code for native methods as an opaque string.
   * 
   * Note that methods and fields are not added to their classes here, that
   * isn't done until {@link GenerateJavaAST}.
   */
  private class BuildDeclMapVisitor extends SafeASTVisitor {

    private String currentFileName;
    private int[] currentSeparatorPositions;
    private final List<TypeDeclaration> typeDecls = new ArrayList<TypeDeclaration>();

    public TypeDeclaration[] getTypeDeclarataions() {
      return typeDecls.toArray(new TypeDeclaration[typeDecls.size()]);
    }

    @Override
    public boolean visit(AnnotationMethodDeclaration methodDeclaration, ClassScope scope) {
      return visit((MethodDeclaration) methodDeclaration, scope);
    }

    @Override
    public boolean visit(Argument argument, BlockScope scope) {
      try {
        if (scope == scope.methodScope()) {
          return true;
        }

        JMethodBody enclosingBody = findEnclosingMethod(scope);
        if (enclosingBody == null) {
          // Happens in the case of external types
          return true;
        }
        SourceInfo info = makeSourceInfo(argument, enclosingBody.getMethod());
        LocalVariableBinding b = argument.binding;
        JType localType = getType(b.type);
        JLocal newLocal =
            JProgram.createLocal(info, String.valueOf(argument.name), localType, b.isFinal(),
                enclosingBody);
        typeMap.put(b, newLocal);
        return true;
      } catch (Throwable e) {
        throw translateException(argument, e);
      }
    }

    @Override
    public boolean visit(ConstructorDeclaration ctorDecl, ClassScope scope) {
      try {
        MethodBinding b = ctorDecl.binding;
        JClassType enclosingType = (JClassType) getType(scope.enclosingSourceType());
        SourceInfo info = makeSourceInfo(ctorDecl, enclosingType);
        processConstructor(b, ctorDecl, info);
        return true;
      } catch (Throwable e) {
        throw translateException(ctorDecl, e);
      }
    }

    @Override
    public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
      try {
        FieldBinding b = fieldDeclaration.binding;
        JDeclaredType enclosingType = (JDeclaredType) getType(scope.enclosingSourceType());
        SourceInfo info = makeSourceInfo(fieldDeclaration, enclosingType);
        Expression initialization = fieldDeclaration.initialization;
        if (initialization != null && initialization instanceof AllocationExpression
            && ((AllocationExpression) initialization).enumConstant != null) {
          createEnumField(info, b, enclosingType);
        } else {
          createField(info, b, enclosingType);
        }
        return true;
      } catch (Throwable e) {
        throw translateException(fieldDeclaration, e);
      }
    }

    @Override
    public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
      try {
        LocalVariableBinding b = localDeclaration.binding;
        TypeBinding resolvedType = localDeclaration.type.resolvedType;
        JType localType;
        if (resolvedType.constantPoolName() != null) {
          localType = getType(resolvedType);
        } else {
          // Special case, a statically unreachable local type.
          localType = JNullType.INSTANCE;
        }
        JMethodBody enclosingBody = findEnclosingMethod(scope);
        if (enclosingBody == null) {
          // Happens in the case of external types
          return true;
        }
        SourceInfo info = makeSourceInfo(localDeclaration, enclosingBody.getMethod());
        JLocal newLocal =
            JProgram.createLocal(info, String.valueOf(localDeclaration.name), localType, b
                .isFinal(), enclosingBody);
        typeMap.put(b, newLocal);
        return true;
      } catch (Throwable e) {
        throw translateException(localDeclaration, e);
      }
    }

    @Override
    public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
      try {
        MethodBinding b = methodDeclaration.binding;
        JDeclaredType enclosingType = (JDeclaredType) getType(scope.enclosingSourceType());
        SourceInfo info = makeSourceInfo(methodDeclaration, enclosingType);
        JMethod newMethod = processMethodBinding(b, enclosingType, info);
        SourceInfo methodInfo = makeSourceInfo(methodDeclaration, newMethod);
        mapParameters(newMethod, methodDeclaration, methodInfo);
        info.addCorrelation(info.getCorrelator().by(newMethod));

        if (newMethod.isNative()) {
          processNativeMethod(methodDeclaration, info, enclosingType, newMethod);
        }

        return true;
      } catch (Throwable e) {
        throw translateException(methodDeclaration, e);
      }
    }

    @Override
    public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
      return process(memberTypeDeclaration);
    }

    @Override
    public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
      return process(typeDeclaration);
    }

    @Override
    public boolean visitValid(TypeDeclaration localTypeDeclaration, BlockScope scope) {
      return process(localTypeDeclaration);
    }

    private JField createEnumField(SourceInfo info, FieldBinding binding,
        JReferenceType enclosingType) {
      JType type = getType(binding.type);
      JField field =
          program.createEnumField(info, String.valueOf(binding.name), (JEnumType) enclosingType,
              (JClassType) type, binding.original().id);
      info.addCorrelation(info.getCorrelator().by(field));
      typeMap.put(binding, field);
      return field;
    }

    private JMethodBody findEnclosingMethod(BlockScope scope) {
      JMethod method;
      MethodScope methodScope = scope.methodScope();
      if (methodScope.isInsideInitializer()) {
        JDeclaredType enclosingType =
            (JDeclaredType) getType(scope.classScope().referenceContext.binding);
        if (methodScope.isStatic) {
          // clinit
          method = enclosingType.getMethods().get(0);
        } else {
          // init
          assert (enclosingType instanceof JClassType);
          method = enclosingType.getMethods().get(1);
        }
      } else {
        AbstractMethodDeclaration referenceMethod = methodScope.referenceMethod();
        method = (JMethod) typeMap.get(referenceMethod.binding);
      }
      assert !method.isNative() && !method.isAbstract();
      return (JMethodBody) (method.isExternal() ? null : method.getBody());
    }

    private SourceInfo makeSourceInfo(AbstractMethodDeclaration methodDecl, HasSourceInfo enclosing) {
      int startLine =
          Util.getLineNumber(methodDecl.sourceStart, currentSeparatorPositions, 0,
              currentSeparatorPositions.length - 1);
      SourceOrigin toReturn =
          SourceOrigin.create(methodDecl.sourceStart, methodDecl.bodyEnd, startLine,
              currentFileName);
      if (enclosing != null) {
        return enclosing.getSourceInfo().makeChild(toReturn);
      }
      return toReturn;
    }

    private SourceInfo makeSourceInfo(Statement stmt, HasSourceInfo enclosing) {
      int startLine =
          Util.getLineNumber(stmt.sourceStart, currentSeparatorPositions, 0,
              currentSeparatorPositions.length - 1);
      SourceOrigin toReturn =
          SourceOrigin.create(stmt.sourceStart, stmt.sourceEnd, startLine, currentFileName);
      if (enclosing != null) {
        return enclosing.getSourceInfo().makeChild(toReturn);
      }
      return toReturn;
    }

    /**
     * Add synthetic fields, setup super types. You'll notice that we DON'T have
     * any concept of "inner" or "outer" types in our AST. Truth is, we found it
     * easier to simply model everything as flat classes and emulate the nesting
     * behavior (and final local access on local classes). It's much closer to
     * how we'll eventually be generating JavaScript code (code generation is
     * more straightforward), it makes for fewer kinds of things to worry about
     * when optimizing (more aggressive optimizations), and it's how Java
     * actually implements the stuff under the hood anyway.
     */
    private boolean process(TypeDeclaration typeDeclaration) {
      CompilationResult compResult = typeDeclaration.compilationResult;
      currentSeparatorPositions = compResult.lineSeparatorPositions;
      currentFileName = String.valueOf(compResult.fileName);

      if (BuildTypeMap.this.process(typeDeclaration.binding)) {
        if (!linker.isExternalType(dotify(typeDeclaration.binding.compoundName))) {
          typeDecls.add(typeDeclaration);
        }
        return true;
      }

      return false;
    }

    private void processNativeMethod(MethodDeclaration methodDeclaration, SourceInfo info,
        JDeclaredType enclosingType, JMethod newMethod) {
      // TODO: use existing parsed JSNI functions from CompilationState.
      // Handle JSNI block
      char[] source = methodDeclaration.compilationResult().getCompilationUnit().getContents();
      String unitSource = String.valueOf(source);
      JsFunction jsFunction =
          JsniCollector.parseJsniFunction(methodDeclaration, unitSource, enclosingType.getName(),
              info, jsProgram.getScope());
      if (jsFunction != null) {
        jsFunction.setFromJava(true);
        ((JsniMethodBody) newMethod.getBody()).setFunc(jsFunction);
        // Ensure that we've resolved the parameter and local references within
        // the JSNI method for later pruning.
        JsParameterResolver localResolver = new JsParameterResolver(jsFunction);
        localResolver.accept(jsFunction);
      }
    }

    private InternalCompilerException translateException(AbstractMethodDeclaration amd, Throwable e) {
      if (e instanceof VirtualMachineError) {
        // Always rethrow VM errors (an attempt to wrap may fail).
        throw (VirtualMachineError) e;
      }
      InternalCompilerException ice;
      if (e instanceof InternalCompilerException) {
        ice = (InternalCompilerException) e;
      } else {
        ice = new InternalCompilerException("Error building type map", e);
      }
      ice.addNode(amd.getClass().getName(), amd.toString(), makeSourceInfo(amd, null));
      return ice;
    }

    private InternalCompilerException translateException(Statement stmt, Throwable e) {
      if (e instanceof VirtualMachineError) {
        // Always rethrow VM errors (an attempt to wrap may fail).
        throw (VirtualMachineError) e;
      }
      InternalCompilerException ice;
      if (e instanceof InternalCompilerException) {
        ice = (InternalCompilerException) e;
      } else {
        ice = new InternalCompilerException("Error building type map", e);
      }
      ice.addNode(stmt.getClass().getName(), stmt.toString(), makeSourceInfo(stmt, null));
      return ice;
    }
  }

  /**
   * Creates JNodes for every type and memorizes the mapping from the JDT
   * Binding to the corresponding JNode for each created type. Note that since
   * there could be forward references, it is not possible to set up super
   * types; it must be done is a subsequent pass.
   */
  private class BuildTypeMapVisitor extends SafeASTVisitor {

    @Override
    public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
      return process(memberTypeDeclaration);
    }

    @Override
    public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
      return process(typeDeclaration);
    }

    @Override
    public boolean visitValid(TypeDeclaration localTypeDeclaration, BlockScope scope) {
      assert (TypeDeclaration.kind(localTypeDeclaration.modifiers) != TypeDeclaration.INTERFACE_DECL);
      return process(localTypeDeclaration);
    }

    private SourceInfo makeSourceInfo(TypeDeclaration typeDecl) {
      CompilationResult compResult = typeDecl.compilationResult;
      int[] indexes = compResult.lineSeparatorPositions;
      String fileName = String.valueOf(compResult.fileName);
      int startLine = Util.getLineNumber(typeDecl.sourceStart, indexes, 0, indexes.length - 1);
      return program.createSourceInfo(typeDecl.sourceStart, typeDecl.bodyEnd, startLine, fileName);
    }

    private boolean process(TypeDeclaration typeDeclaration) {
      try {
        SourceTypeBinding binding = typeDeclaration.binding;
        String name = dotify(binding.compoundName);
        if (binding instanceof LocalTypeBinding) {
          char[] localName = binding.constantPoolName();
          name = new String(localName).replace('/', '.');
        }

        SourceInfo info = makeSourceInfo(typeDeclaration);
        typeMap.put(binding, createType(name, info, binding));
        return true;
      } catch (Throwable e) {
        throw translateException(typeDeclaration, e);
      }
    }

    private InternalCompilerException translateException(TypeDeclaration typeDecl, Throwable e) {
      if (e instanceof VirtualMachineError) {
        // Always rethrow VM errors (an attempt to wrap may fail).
        throw (VirtualMachineError) e;
      }
      InternalCompilerException ice;
      if (e instanceof InternalCompilerException) {
        ice = (InternalCompilerException) e;
      } else {
        ice = new InternalCompilerException("Error building type map", e);
      }
      ice.addNode(typeDecl.getClass().getName(), typeDecl.toString(), makeSourceInfo(typeDecl));
      return ice;
    }
  }

  private class ExternalTypeCreator implements ExternalTypeTask {

    public void process(String klass, BinaryTypeBinding binding) {
      if (program.getFromTypeMap(klass) == null) {
        // NB(tobyr) There are a few cases where certain compiler intrinsic
        // types are only needed if the program references them
        // (e.g. boxed numeric types). If we don't have the binding for those
        // types, we can safely ignore it.
        createExternalType(klass, binding);
      }
    }
  }

  private class ExternalTypeResolver implements ExternalTypeTask {

    public void process(String klass, BinaryTypeBinding binding) {
      if (binding != null) {
        JDeclaredType type = program.getFromTypeMap(klass);
        resolve(type, binding);
      }
    }
  }

  private interface ExternalTypeTask {

    void process(String klass, BinaryTypeBinding binding);
  }

  /**
   * Resolves the scope of JS identifiers solely within the scope of a method.
   */
  private static class JsParameterResolver extends JsAbstractSymbolResolver {
    private final JsFunction jsFunction;

    public JsParameterResolver(JsFunction jsFunction) {
      this.jsFunction = jsFunction;
    }

    @Override
    public void resolve(JsNameRef x) {
      // Only resolve unqualified names
      if (x.getQualifier() == null) {
        JsName name = getScope().findExistingName(x.getIdent());

        // Ensure that we're resolving a name from the function's parameters
        JsNode node = name == null ? null : name.getStaticRef();
        if (node instanceof JsParameter) {
          JsParameter param = (JsParameter) node;
          if (jsFunction.getParameters().contains(param)) {
            x.resolve(name);
          }
        }
      }
    }
  }

  // TODO: Remove this overload altogether at some point.

  public static TypeDeclaration[] exec(TypeMap typeMap, CompilationResults results,
      JsProgram jsProgram, TypeLinker linker) {
    BuildTypeMap btm = new BuildTypeMap(typeMap, jsProgram, linker, results.compiledUnits);
    Event buildTypeMapEvent = SpeedTracerLogger.start(CompilerEventType.BUILD_TYPE_MAP_FOR_AST);
    btm.createPeersForUnits();
    btm.resolveExternalTypes(results.binaryBindings);
    TypeDeclaration[] result = btm.createPeersForNonTypeDecls();
    buildTypeMapEvent.end();
    return result;
  }

  public static TypeDeclaration[] exec(TypeMap typeMap, CompilationUnitDeclaration[] unitDecls,
      JsProgram jsProgram) {
    CompilationResults results =
        new CompilationResults(unitDecls, new HashMap<String, BinaryTypeBinding>(0));
    return exec(typeMap, results, jsProgram, TypeLinker.NULL_TYPE_LINKER);
  }

  static String dotify(char[][] name) {
    StringBuffer result = new StringBuffer();
    for (int i = 0; i < name.length; ++i) {
      if (i > 0) {
        result.append('.');
      }

      result.append(name[i]);
    }
    return result.toString();
  }

  private final JsProgram jsProgram;
  private final TypeLinker linker;
  private final JProgram program;
  private final TypeMap typeMap;
  private final CompilationUnitDeclaration[] unitDecls;

  private BuildTypeMap(TypeMap typeMap, JsProgram jsProgram, TypeLinker linker,
      CompilationUnitDeclaration[] unitDecls) {
    this.typeMap = typeMap;
    this.program = typeMap.getProgram();
    this.jsProgram = jsProgram;
    this.linker = linker;
    this.unitDecls = unitDecls;
  }

  private void addThrownExceptions(MethodBinding methodBinding, JMethod method) {
    for (ReferenceBinding thrownBinding : methodBinding.thrownExceptions) {
      JClassType type = (JClassType) getType(thrownBinding.erasure());
      method.addThrownException(type);
    }
  }

  private JDeclaredType createExternalType(String name, ReferenceBinding binding) {
    char[] chars = binding.getFileName();
    String fileName = chars == null ? "" : String.valueOf(chars);
    SourceInfo sourceInfo = SourceOrigin.create(0, fileName);
    JDeclaredType type = createType(name, sourceInfo, binding);
    typeMap.put(binding, type);
    return type;
  }

  private JField createField(SourceInfo info, FieldBinding binding, JDeclaredType enclosingType) {
    JType type = getType(binding.type);
    JField field =
        program.createField(info, String.valueOf(binding.name), enclosingType, type, binding
            .isStatic(), GwtAstBuilder.getFieldDisposition(binding));
    typeMap.put(binding, field);
    info.addCorrelation(info.getCorrelator().by(field));
    return field;
  }

  private JField createField(SyntheticArgumentBinding binding, JDeclaredType enclosingType,
      Disposition disposition) {
    JType type = getType(binding.type);
    SourceInfo info = enclosingType.getSourceInfo().makeChild();
    JField field =
        program.createField(info, String.valueOf(binding.name), enclosingType, type, false,
            disposition);
    info.addCorrelation(info.getCorrelator().by(field));
    if (binding.matchingField != null) {
      typeMap.put(binding.matchingField, field);
    }
    typeMap.put(binding, field);
    return field;
  }

  private void createMethod(MethodBinding binding, SourceInfo info) {
    JDeclaredType enclosingType = (JDeclaredType) getType(binding.declaringClass);
    JMethod newMethod = processMethodBinding(binding, enclosingType, info);
    mapParameters(newMethod, binding, info);
  }

  private JParameter createParameter(LocalVariableBinding binding, JMethod enclosingMethod,
      SourceInfo info) {
    JType type = getType(binding.type);
    JParameter param =
        JProgram.createParameter(info, String.valueOf(binding.name), type, binding.isFinal(),
            false, enclosingMethod);
    typeMap.put(binding, param);
    return param;
  }

  private JParameter createParameter(SyntheticArgumentBinding arg, String argName,
      JMethod enclosingMethod) {
    JType type = getType(arg.type);
    JParameter param =
        JProgram.createParameter(enclosingMethod.getSourceInfo(), argName, type, true, false,
            enclosingMethod);
    return param;
  }

  private JParameter createParameter(TypeBinding paramType, JMethod enclosingMethod,
      SourceInfo info, int argPosition) {
    JType type = getType(paramType);
    // TODO(tobyr) Get the actual param name if it's present in debug info
    // or otherwise.
    String syntheticParamName = "arg" + argPosition;
    JParameter param =
        JProgram.createParameter(info, syntheticParamName, type, true, false, enclosingMethod);
    // Don't need to put the parameter in the TypeMap as it won't be looked
    // up for binary types.
    return param;
  }

  private TypeDeclaration[] createPeersForNonTypeDecls() {
    // Traverse to create our JNode peers for each method, field,
    // parameter, and local
    BuildDeclMapVisitor v = new BuildDeclMapVisitor();
    for (CompilationUnitDeclaration unitDecl : unitDecls) {
      unitDecl.traverse(v, unitDecl.scope);
    }
    return v.getTypeDeclarataions();
  }

  private void createPeersForUnits() {
    // Traverse to create our JNode peers for each type
    BuildTypeMapVisitor v = new BuildTypeMapVisitor();
    for (CompilationUnitDeclaration unitDecl : unitDecls) {
      unitDecl.traverse(v, unitDecl.scope);
    }
  }

  private JDeclaredType createType(String name, SourceInfo info, ReferenceBinding binding) {

    JDeclaredType newType;
    if (binding.isClass()) {
      newType = program.createClass(info, name, binding.isAbstract(), binding.isFinal());
    } else if (binding.isInterface() || binding.isAnnotationType()) {
      newType = program.createInterface(info, name);
    } else if (binding.isEnum()) {
      if (binding.isAnonymousType()) {
        // Don't model an enum subclass as a JEnumType.
        newType = program.createClass(info, name, false, true);
      } else {
        newType = program.createEnum(info, name, binding.isAbstract());
      }
    } else {
      throw new InternalCompilerException("ReferenceBinding is not a class, interface, or enum.");
    }

    info.addCorrelation(info.getCorrelator().by(newType));

    /**
     * We emulate static initializers and instance initializers as methods. As
     * in other cases, this gives us: simpler AST, easier to optimize, more like
     * output JavaScript. Clinit is always in slot 0, init (if it exists) is
     * always in slot 1.
     */
    SourceInfo child = info.makeChild();
    JMethod clinit =
        program.createMethod(child, "$clinit", newType, program.getTypeVoid(), false, true, true,
            true, false);
    clinit.freezeParamTypes();
    clinit.setSynthetic();
    child.addCorrelation(info.getCorrelator().by(clinit));

    if (newType instanceof JClassType) {
      child = info.makeChild();
      JMethod init =
          program.createMethod(child, "$init", newType, program.getTypeVoid(), false, false, true,
              true, false);
      init.freezeParamTypes();
      init.setSynthetic();
      child.addCorrelation(info.getCorrelator().by(init));
    }

    newType.setExternal(linker.isExternalType(newType.getName()));
    return newType;
  }

  private void forEachExternalType(Map<String, BinaryTypeBinding> bindings, ExternalTypeTask task) {
    for (Map.Entry<String, BinaryTypeBinding> entry : bindings.entrySet()) {
      String klass = entry.getKey();
      if (linker.isExternalType(klass)) {
        BinaryTypeBinding binding = bindings.get(klass);
        if (binding != null) {
          task.process(klass, binding);
        }
      }
    }
  }

  private JType getType(TypeBinding binding) {
    JType type = (JType) typeMap.tryGet(binding);

    if (type != null) {
      return type;
    }

    if (binding instanceof ArrayBinding) {
      binding = ((ArrayBinding) binding).leafComponentType;
    }

    if (!(binding instanceof ReferenceBinding)) {
      throw new InternalCompilerException("Expected a ReferenceBinding but received a "
          + binding.getClass());
    }

    ReferenceBinding refBinding = (ReferenceBinding) binding;
    String name = dotify(refBinding.compoundName);
    if (!linker.isExternalType(name)) {
      // typeMap.get() will fail with an appropriate exception
      return (JType) typeMap.get(binding);
    }

    type = createExternalType(name, refBinding);
    resolve((JDeclaredType) type, refBinding);
    return type;
  }

  private void mapParameters(JMethod method, AbstractMethodDeclaration x, SourceInfo info) {
    MethodBinding b = x.binding;
    int paramCount = (b.parameters != null ? b.parameters.length : 0);
    if (paramCount > 0) {
      for (int i = 0, n = x.arguments.length; i < n; ++i) {
        createParameter(x.arguments[i].binding, method, info);
      }
    }
    method.freezeParamTypes();
  }

  private void mapParameters(JMethod method, MethodBinding binding, SourceInfo info) {
    int paramCount = binding.parameters != null ? binding.parameters.length : 0;
    if (paramCount > 0) {
      int counter = 0;
      for (TypeBinding argType : binding.parameters) {
        createParameter(argType, method, info, counter++);
      }
    }
    method.freezeParamTypes();
  }

  private boolean process(ReferenceBinding binding) {
    JDeclaredType type = (JDeclaredType) getType(binding);

    try {
      // Create an override for getClass().
      if (type instanceof JClassType && type != program.getTypeJavaLangObject()) {

        SourceInfo info = type.getSourceInfo().makeChild();
        JMethod getClassMethod =
            program.createMethod(info, "getClass", type, program.getTypeJavaLangClass(), false,
                false, false, false, false);
        assert (type.getMethods().get(2) == getClassMethod);
        getClassMethod.freezeParamTypes();
        getClassMethod.setSynthetic();
        info.addCorrelation(info.getCorrelator().by(getClassMethod));
      }

      if (binding.isNestedType() && !binding.isStatic() && !(binding instanceof BinaryTypeBinding)) {
        // TODO(tobyr) Do something here for binary types?

        // add synthetic fields for outer this and locals
        assert (type instanceof JClassType);
        NestedTypeBinding nestedBinding = (NestedTypeBinding) binding;
        if (nestedBinding.enclosingInstances != null) {
          for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
            SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
            createField(arg, type, Disposition.THIS_REF);
          }
        }

        if (nestedBinding.outerLocalVariables != null) {
          for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
            SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
            // See InnerClassTest.testOuterThisFromSuperCall().
            boolean isReallyThisRef = false;
            if (arg.actualOuterLocalVariable instanceof SyntheticArgumentBinding) {
              SyntheticArgumentBinding outer =
                  (SyntheticArgumentBinding) arg.actualOuterLocalVariable;
              if (outer.matchingField != null) {
                JField field = (JField) typeMap.get(outer.matchingField);
                if (field.isThisRef()) {
                  isReallyThisRef = true;
                }
              }
            }
            createField(arg, type, isReallyThisRef ? Disposition.THIS_REF : Disposition.FINAL);
          }
        }
      }

      ReferenceBinding superClassBinding = binding.superclass();
      if (type instanceof JClassType && superClassBinding != null) {
        // TODO: handle separately?
        assert (binding.superclass().isClass() || binding.superclass().isEnum());
        JClassType superClass = (JClassType) getType(superClassBinding);
        ((JClassType) type).setSuperClass(superClass);
      }

      ReferenceBinding[] superInterfaces = binding.superInterfaces();
      for (ReferenceBinding superInterfaceBinding : superInterfaces) {
        assert (superInterfaceBinding.isInterface());
        JInterfaceType superInterface = (JInterfaceType) getType(superInterfaceBinding);
        type.addImplements(superInterface);
      }

      ReferenceBinding enclosingBinding = binding.enclosingType();
      if (enclosingBinding != null) {
        type.setEnclosingType((JDeclaredType) getType(enclosingBinding));
      }

      if (type instanceof JEnumType) {
        processEnumType(binding, (JEnumType) type);
      }

      return true;
    } catch (VirtualMachineError e) {
      // Always rethrow VM errors (an attempt to wrap may fail).
      throw e;
    } catch (InternalCompilerException ice) {
      ice.addNode(type);
      throw ice;
    } catch (Throwable e) {
      throw new InternalCompilerException(type, "Error building type map", e);
    }
  }

  private JConstructor processConstructor(MethodBinding b, ConstructorDeclaration decl,
      SourceInfo info) {
    JClassType enclosingType = (JClassType) getType(b.declaringClass);
    JConstructor newCtor = program.createConstructor(info, enclosingType);

    // Enums have hidden arguments for name and value
    if (enclosingType.isEnumOrSubclass() != null) {
      JProgram.createParameter(info, "enum$name", program.getTypeJavaLangString(), true, false,
          newCtor);
      JProgram.createParameter(info, "enum$ordinal", program.getTypePrimitiveInt(), true, false,
          newCtor);
    }

    ReferenceBinding declaringClass = b.declaringClass;
    Set<String> alreadyNamedVariables = new HashSet<String>();
    if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
      // TODO(tobyr) Do we have to do the equivalent for binary types here
      // or will this just fall out correctly?

      // add synthetic args for outer this
      NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
      if (nestedBinding.enclosingInstances != null) {
        for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
          SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
          String argName = String.valueOf(arg.name);
          if (alreadyNamedVariables.contains(argName)) {
            argName += "_" + i;
          }
          createParameter(arg, argName, newCtor);
          alreadyNamedVariables.add(argName);
        }
      }
    }

    // user args
    if (decl == null) {
      mapParameters(newCtor, b, info);
    } else {
      mapParameters(newCtor, decl, info);
    }
    // original params are now frozen

    addThrownExceptions(b, newCtor);

    info.addCorrelation(info.getCorrelator().by(newCtor));

    if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
      // add synthetic args for locals
      NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
      // add synthetic args for outer this and locals
      if (nestedBinding.outerLocalVariables != null) {
        for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
          SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
          String argName = String.valueOf(arg.name);
          if (alreadyNamedVariables.contains(argName)) {
            argName += "_" + i;
          }
          createParameter(arg, argName, newCtor);
          alreadyNamedVariables.add(argName);
        }
      }
    }

    if (enclosingType.isExternal()) {
      newCtor.setBody(null);
    }

    typeMap.put(b, newCtor);
    return newCtor;
  }

  private void processEnumType(ReferenceBinding binding, JEnumType type) {
    // Visit the synthetic values() and valueOf() methods.
    for (MethodBinding methodBinding : binding.methods()) {
      if (methodBinding instanceof SyntheticMethodBinding) {
        JMethod newMethod = processMethodBinding(methodBinding, type, type.getSourceInfo());
        TypeBinding[] parameters = methodBinding.parameters;
        if (parameters.length == 0) {
          assert newMethod.getName().equals("values");
        } else if (parameters.length == 1) {
          assert newMethod.getName().equals("valueOf");
          assert typeMap.get(parameters[0]) == program.getTypeJavaLangString();
          JProgram.createParameter(newMethod.getSourceInfo(), "name", program
              .getTypeJavaLangString(), true, false, newMethod);
        } else {
          assert false;
        }
        newMethod.freezeParamTypes();
      }
    }
  }

  private void processExternalMethod(MethodBinding binding, JDeclaredType type) {
    if (binding.isPrivate()
        || (type.getName().startsWith("java.") && !binding.isPublic() && !binding.isProtected())) {
      return;
    }
    if (binding.isConstructor()) {
      processConstructor(binding, null, type.getSourceInfo());
    } else {
      createMethod(binding, type.getSourceInfo());
    }
  }

  private JMethod processMethodBinding(MethodBinding b, JDeclaredType enclosingType, SourceInfo info) {
    JType returnType = getType(b.returnType);
    JMethod newMethod =
        program.createMethod(info, String.valueOf(b.selector), enclosingType, returnType, b
            .isAbstract(), b.isStatic(), b.isFinal(), b.isPrivate(), b.isNative());
    addThrownExceptions(b, newMethod);
    if (b.isSynthetic()) {
      newMethod.setSynthetic();
    }

    if (enclosingType.isExternal()) {
      newMethod.setBody(null);
    }
    typeMap.put(b, newMethod);
    return newMethod;
  }

  private void resolve(JDeclaredType type, ReferenceBinding binding) {
    process(binding);

    for (FieldBinding fieldBinding : binding.fields()) {
      if (fieldBinding.isPrivate()
          || (type.getName().startsWith("java.") && !fieldBinding.isPublic() && !fieldBinding
              .isProtected())) {
        continue;
      }

      createField(type.getSourceInfo(), fieldBinding, type);
    }

    for (MethodBinding methodBinding : binding.methods()) {
      processExternalMethod(methodBinding, type);
    }

    if (binding instanceof BinaryTypeBinding) {
      // Unlike SourceTypeBindings, we have to explicitly ask for bridge methods
      // for BinaryTypeBindings.
      try {
        // TODO(tobyr) Fix so we don't have to use reflection.
        Method m = BinaryTypeBinding.class.getDeclaredMethod("bridgeMethods");
        MethodBinding[] bridgeMethods = (MethodBinding[]) m.invoke(binding);

        for (MethodBinding methodBinding : bridgeMethods) {
          processExternalMethod(methodBinding, type);
        }
      } catch (Exception e) {
        throw new InternalCompilerException("Unexpected failure", e);
      }
    }
  }

  /**
   * Creates and resolves all external types.
   */
  private void resolveExternalTypes(Map<String, BinaryTypeBinding> bindings) {
    forEachExternalType(bindings, new ExternalTypeCreator());
    forEachExternalType(bindings, new ExternalTypeResolver());
  }
}
