/*
 * Copyright 2010 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.CompilerContext;
import com.google.gwt.dev.common.InliningMode;
import com.google.gwt.dev.javac.JdtUtil;
import com.google.gwt.dev.javac.JsInteropUtil;
import com.google.gwt.dev.javac.JsniMethod;
import com.google.gwt.dev.jdt.SafeASTVisitor;
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.AccessModifier;
import com.google.gwt.dev.jjs.ast.CanHaveSuppressedWarnings;
import com.google.gwt.dev.jjs.ast.HasJsInfo;
import com.google.gwt.dev.jjs.ast.HasJsInfo.JsMemberType;
import com.google.gwt.dev.jjs.ast.JArrayLength;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JAssertStatement;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
import com.google.gwt.dev.jjs.ast.JBreakStatement;
import com.google.gwt.dev.jjs.ast.JCaseStatement;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JCharLiteral;
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.JContinueStatement;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JDoStatement;
import com.google.gwt.dev.jjs.ast.JDoubleLiteral;
import com.google.gwt.dev.jjs.ast.JEnumField;
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.JField.Disposition;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JFloatLiteral;
import com.google.gwt.dev.jjs.ast.JForStatement;
import com.google.gwt.dev.jjs.ast.JIfStatement;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JIntLiteral;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JLabel;
import com.google.gwt.dev.jjs.ast.JLabeledStatement;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JLongLiteral;
import com.google.gwt.dev.jjs.ast.JMember;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.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.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JPostfixOperation;
import com.google.gwt.dev.jjs.ast.JPrefixOperation;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JSwitchStatement;
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JThrowStatement;
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.JUnsafeTypeCoercion;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.ast.js.JsniClassLiteral;
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.js.JsAbstractSymbolResolver;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsModVisitor;
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.util.StringInterner;
import com.google.gwt.dev.util.collect.Stack;
import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.base.Joiner;
import com.google.gwt.thirdparty.guava.common.base.Preconditions;
import com.google.gwt.thirdparty.guava.common.base.Predicate;
import com.google.gwt.thirdparty.guava.common.base.Predicates;
import com.google.gwt.thirdparty.guava.common.collect.Collections2;
import com.google.gwt.thirdparty.guava.common.collect.FluentIterable;
import com.google.gwt.thirdparty.guava.common.collect.Interner;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
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.Sets;
import com.google.gwt.util.regexfilter.WhitelistRegexFilter;

import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
import org.eclipse.jdt.internal.compiler.ast.CastExpression;
import org.eclipse.jdt.internal.compiler.ast.CharLiteral;
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.eclipse.jdt.internal.compiler.ast.Clinit;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ContinueStatement;
import org.eclipse.jdt.internal.compiler.ast.DoStatement;
import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
import org.eclipse.jdt.internal.compiler.ast.EmptyStatement;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral;
import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
import org.eclipse.jdt.internal.compiler.ast.ForStatement;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
import org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
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.IntersectionTypeBinding18;
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.MethodVerifier;
import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
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.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
import org.eclipse.jdt.internal.compiler.util.Util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Constructs a GWT Java AST from a single isolated compilation unit. The AST is
 * not associated with any {@link com.google.gwt.dev.jjs.ast.JProgram} and will
 * contain unresolved references.
 */
public class GwtAstBuilder {

  public static final String CLINIT_METHOD_NAME = "$clinit";
  public static final String GET_CLASS_METHOD_NAME = "getClass";
  public static final String EQUALS_METHOD_NAME = "equals";
  public static final String HAS_NEXT_METHOD_NAME = "hasNext";
  public static final String HASHCODE_METHOD_NAME = "hashCode";
  public static final String ITERATOR_METHOD_NAME = "iterator";
  public static final String INIT_NAME_METHOD_NAME = "$init";
  public static final String NEXT_METHOD_NAME = "next";
  public static final String ORDINAL_METHOD_NAME = "ordinal";
  public static final String OUTER_LAMBDA_PARAM_NAME = "$$outer_0";
  public static final String STATIC_INIT_METHOD_NAME =  "$" + INIT_NAME_METHOD_NAME;
  public static final String TO_STRING_METHOD_NAME = "toString";
  public static final String VALUE_OF_METHOD_NAME = "valueOf";
  public static final String VALUES_METHOD_NAME = "values";

  public static final int CLINIT_METHOD_INDEX = 0;
  public static final int INIT_METHOD_INDEX = 1;
  public static final int GET_CLASS_METHOD_INDEX = 2;

  /**
   * Visit the JDT AST and produce our own AST. By the end of this pass, the
   * produced AST should contain every piece of information we'll ever need
   * about the code. The JDT nodes should never again be referenced after this.
   */
  class AstVisitor extends SafeASTVisitor {
    /**
     * Collects JSNI references from native method bodies and replaces the ones referring to
     * compile time constants by their corresponding constant value.
     */
    private class JsniReferenceCollector extends JsModVisitor {
      private final JsniMethodBody nativeMethodBody;

      private JsniReferenceCollector(JsniMethodBody nativeMethodBody) {
        this.nativeMethodBody = nativeMethodBody;
      }

      @Override
      public void endVisit(JsNameRef x, JsContext ctx) {
        if (!x.isJsniReference()) {
          return;
        }
        String ident = x.getIdent();
        Binding binding = jsniRefs.get(ident);
        SourceInfo info = x.getSourceInfo();
        assert binding != null;
        if (binding instanceof TypeBinding) {
          JType type = typeMap.get((TypeBinding) binding);
          processClassLiteral(x, info, type, ctx);
        } else if (binding instanceof FieldBinding) {
          FieldBinding fieldBinding = (FieldBinding) binding;
          if (isOptimizableCompileTimeConstant(fieldBinding)) {
            // Replace any compile-time constants with the constant value of the field.
            assert !ctx.isLvalue();
            JExpression constant = getConstant(info, fieldBinding.constant());
            JsExpression result = JjsUtils.translateLiteral((JLiteral) constant);
            assert (result != null);
            ctx.replaceMe(result);
          } else {
            // Normal: create a jsniRef.
            JField field = typeMap.get(fieldBinding);
            processField(x, info, field, ctx);
          }
        } else {
          JMethod method = typeMap.get((MethodBinding) binding);
          processMethod(x, info, method);
        }
      }

      private void processClassLiteral(JsNameRef nameRef, SourceInfo info, JType type,
          JsContext ctx) {
        assert !ctx.isLvalue();
        JsniClassLiteral classLiteral = new JsniClassLiteral(info, nameRef.getIdent(), type);
        nativeMethodBody.addClassRef(classLiteral);
      }

      private void processField(JsNameRef nameRef, SourceInfo info, JField field, JsContext ctx) {
        JsniFieldRef fieldRef =
            new JsniFieldRef(info, nameRef.getIdent(), field, curClass.type, ctx.isLvalue());
        nativeMethodBody.addJsniRef(fieldRef);
      }

      private void processMethod(JsNameRef nameRef, SourceInfo info, JMethod method) {
        JsniMethodRef methodRef =
            new JsniMethodRef(info, nameRef.getIdent(), method, javaLangObject);
        nativeMethodBody.addJsniRef(methodRef);
      }
    }

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

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

      @Override
      public void resolveQualifiedName(JsNameRef x) {
      }

      @Override
      protected void resolveUnqualifiedName(JsNameRef x) {
        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 (jsFunction.getParameters().contains(node)) {
          assert node instanceof JsParameter;
          x.resolve(name);
        }
      }
    }

    private final Stack<ClassInfo> classStack = new Stack<ClassInfo>();

    private ClassInfo curClass = null;

    private MethodInfo curMethod = null;

    private final Stack<MethodInfo> methodStack = new Stack<MethodInfo>();

    private final List<JNode> nodeStack = Lists.newArrayList();

    @Override
    public void endVisit(AllocationExpression x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        List<JExpression> arguments = popCallArguments(info, x.arguments, x.binding);
        pushNewExpression(info, x, null, arguments, scope);
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(AND_AND_Expression x, BlockScope scope) {
      pushBinaryOp(x, JBinaryOperator.AND);
    }

    @Override
    public void endVisit(AnnotationMethodDeclaration x, ClassScope classScope) {
      endVisit((MethodDeclaration) x, classScope);
    }

    @Override
    public void endVisit(ArrayAllocationExpression x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JArrayType type = (JArrayType) typeMap.get(x.resolvedType);

        if (x.initializer != null) {
          // handled by ArrayInitializer.
        } else {
          List<JExpression> dims = performBoxUnboxConversions(pop(x.dimensions), x.dimensions);
          push(JNewArray.createArrayWithDimensionExpressions(info, type, dims));
        }
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(ArrayInitializer x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
        List<JExpression> expressions =
            performBoxUnboxConversions(pop(x.expressions), x.expressions);
        push(JNewArray.createArrayWithInitializers(info, type, expressions));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(ArrayReference x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JExpression position = pop(x.position);
        JExpression receiver = pop(x.receiver);
        push(new JArrayRef(info, receiver, position));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(AssertStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JExpression exceptionArgument = pop(x.exceptionArgument);
        JExpression assertExpression = pop(x.assertExpression);
        push(new JAssertStatement(info, assertExpression, exceptionArgument));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(Assignment x, BlockScope scope) {
      pushBinaryOp(x, JBinaryOperator.ASG);
    }

    @Override
    public void endVisit(BinaryExpression x, BlockScope scope) {
      JBinaryOperator op;
      int binOp = (x.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
      switch (binOp) {
        case OperatorIds.LEFT_SHIFT:
          op = JBinaryOperator.SHL;
          break;
        case OperatorIds.RIGHT_SHIFT:
          op = JBinaryOperator.SHR;
          break;
        case OperatorIds.UNSIGNED_RIGHT_SHIFT:
          op = JBinaryOperator.SHRU;
          break;
        case OperatorIds.PLUS:
          if (javaLangString == typeMap.get(x.resolvedType)) {
            op = JBinaryOperator.CONCAT;
          } else {
            op = JBinaryOperator.ADD;
          }
          break;
        case OperatorIds.MINUS:
          op = JBinaryOperator.SUB;
          break;
        case OperatorIds.REMAINDER:
          op = JBinaryOperator.MOD;
          break;
        case OperatorIds.XOR:
          op = JBinaryOperator.BIT_XOR;
          break;
        case OperatorIds.AND:
          op = JBinaryOperator.BIT_AND;
          break;
        case OperatorIds.MULTIPLY:
          op = JBinaryOperator.MUL;
          break;
        case OperatorIds.OR:
          op = JBinaryOperator.BIT_OR;
          break;
        case OperatorIds.DIVIDE:
          op = JBinaryOperator.DIV;
          break;
        case OperatorIds.LESS_EQUAL:
          op = JBinaryOperator.LTE;
          break;
        case OperatorIds.GREATER_EQUAL:
          op = JBinaryOperator.GTE;
          break;
        case OperatorIds.GREATER:
          op = JBinaryOperator.GT;
          break;
        case OperatorIds.LESS:
          op = JBinaryOperator.LT;
          break;
        default:
          throw translateException(x, new InternalCompilerException(
              "Unexpected operator for BinaryExpression"));
      }
      pushBinaryOp(x, op);
    }

    @Override
    public void endVisit(Block x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JBlock block = popBlock(info, x.statements);
        push(block);
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(BreakStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        push(new JBreakStatement(info, getOrCreateLabel(info, x.label)));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(CaseStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JExpression caseExpression = pop(x.constantExpression);
        if (caseExpression != null && x.constantExpression.resolvedType.isEnum()) {
          caseExpression = synthesizeCallToOrdinal(scope, info, caseExpression);
        }
        push(new JCaseStatement(info, caseExpression));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(CastExpression x, BlockScope scope) {
      /**
       * Our output of a ((A & I1 & I2) a) looks like this:
       *
       * ((A)(I1)(I2)a).
       */
      try {
        SourceInfo info = makeSourceInfo(x);
        JType[] type = processCastType(x.resolvedType);
        JExpression expression = pop(x.expression);
        push(buildCastOperation(info, type, expression));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(CharLiteral x, BlockScope scope) {
      try {
        push(JCharLiteral.get(x.constant.charValue()));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(ClassLiteralAccess x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JType type = typeMap.get(x.targetType);
        push(new JClassLiteral(info, type));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(CompoundAssignment x, BlockScope scope) {
      JBinaryOperator op;
      switch (x.operator) {
        case OperatorIds.PLUS:
          if (javaLangString == typeMap.get(x.resolvedType)) {
            op = JBinaryOperator.ASG_CONCAT;
          } else {
            op = JBinaryOperator.ASG_ADD;
          }
          break;
        case OperatorIds.MINUS:
          op = JBinaryOperator.ASG_SUB;
          break;
        case OperatorIds.MULTIPLY:
          op = JBinaryOperator.ASG_MUL;
          break;
        case OperatorIds.DIVIDE:
          op = JBinaryOperator.ASG_DIV;
          break;
        case OperatorIds.AND:
          op = JBinaryOperator.ASG_BIT_AND;
          break;
        case OperatorIds.OR:
          op = JBinaryOperator.ASG_BIT_OR;
          break;
        case OperatorIds.XOR:
          op = JBinaryOperator.ASG_BIT_XOR;
          break;
        case OperatorIds.REMAINDER:
          op = JBinaryOperator.ASG_MOD;
          break;
        case OperatorIds.LEFT_SHIFT:
          op = JBinaryOperator.ASG_SHL;
          break;
        case OperatorIds.RIGHT_SHIFT:
          op = JBinaryOperator.ASG_SHR;
          break;
        case OperatorIds.UNSIGNED_RIGHT_SHIFT:
          op = JBinaryOperator.ASG_SHRU;
          break;
        default:
          throw translateException(x, new InternalCompilerException(
              "Unexpected operator for CompoundAssignment"));
      }
      pushBinaryOp(x, op);
    }

    @Override
    public void endVisit(ConditionalExpression x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JType type = typeMap.get(x.resolvedType);
        JExpression valueIfFalse = pop(x.valueIfFalse);
        JExpression valueIfTrue = pop(x.valueIfTrue);
        JExpression condition = pop(x.condition);
        push(new JConditional(info, type, condition, valueIfTrue, valueIfFalse));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(ConstructorDeclaration x, ClassScope scope) {
      try {
        List<JStatement> statements = pop(x.statements);
        JStatement constructorCall = pop(x.constructorCall);
        JBlock block = curMethod.body.getBlock();
        SourceInfo info = curMethod.method.getSourceInfo();

        /*
         * Determine if we have an explicit this call. The presence of an
         * explicit this call indicates we can skip certain initialization steps
         * (as the callee will perform those steps for us). These skippable
         * steps are 1) assigning synthetic args to fields and 2) running
         * initializers.
         */
        boolean hasExplicitThis = (x.constructorCall != null) && !x.constructorCall.isSuperAccess();

        /*
         * All synthetic fields must be assigned, unless we have an explicit
         * this constructor call, in which case the callee will assign them for
         * us.
         */
        if (!hasExplicitThis) {
          ReferenceBinding declaringClass = (ReferenceBinding) x.binding.declaringClass.erasure();
          if (JdtUtil.isInnerClass(declaringClass)) {
            NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
            if (nestedBinding.enclosingInstances != null) {
              for (SyntheticArgumentBinding arg : nestedBinding.enclosingInstances) {
                JBinaryOperation asg = assignSyntheticField(info, arg);
                block.addStmt(asg.makeStatement());
              }
            }

            if (nestedBinding.outerLocalVariables != null) {
              for (SyntheticArgumentBinding arg : nestedBinding.outerLocalVariables) {
                JBinaryOperation asg = assignSyntheticField(info, arg);
                block.addStmt(asg.makeStatement());
              }
            }
          }
        }

        if (constructorCall != null) {
          block.addStmt(constructorCall);
        }

        /*
         * Call the synthetic instance initializer method, unless we have an
         * explicit this constructor call, in which case the callee will.
         */
        if (!hasExplicitThis) {
          JMethod initMethod = curClass.type.getInitMethod();
          JMethodCall initCall = new JMethodCall(info, makeThisRef(info), initMethod);
          block.addStmt(initCall.makeStatement());
        }

        // user code (finally!)
        block.addStmts(statements);
        popMethodInfo();
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(ContinueStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        push(new JContinueStatement(info, getOrCreateLabel(info, x.label)));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(DoStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JExpression condition = pop(x.condition);
        JStatement action = pop(x.action);
        push(new JDoStatement(info, condition, action));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(DoubleLiteral x, BlockScope scope) {
      try {
        push(JDoubleLiteral.get(x.constant.doubleValue()));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(EmptyStatement x, BlockScope scope) {
      push(null);
    }

    @Override
    public void endVisit(EqualExpression x, BlockScope scope) {
      JBinaryOperator op;
      switch ((x.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
        case OperatorIds.EQUAL_EQUAL:
          op = JBinaryOperator.EQ;
          break;
        case OperatorIds.NOT_EQUAL:
          op = JBinaryOperator.NEQ;
          break;
        default:
          throw translateException(x, new InternalCompilerException(
              "Unexpected operator for EqualExpression"));
      }
      pushBinaryOp(x, op);
    }

    @Override
    public void endVisit(ExplicitConstructorCall x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JConstructor ctor = (JConstructor) typeMap.get(x.binding);
        JExpression trueQualifier = makeThisRef(info);
        JMethodCall call = new JMethodCall(info, trueQualifier, ctor);
        List<JExpression> callArgs = popCallArguments(info, x.arguments, x.binding);

        if (curClass.classType.isEnumOrSubclass() != null) {
          // Enums: wire up synthetic name/ordinal params to the super method.
          JParameterRef enumNameRef = curMethod.method.getParams().get(0).makeRef(info);
          call.addArg(enumNameRef);
          JParameterRef enumOrdinalRef = curMethod.method.getParams().get(1).makeRef(info);
          call.addArg(enumOrdinalRef);
        }

        if (x.isSuperAccess()) {
          JExpression qualifier = pop(x.qualification);
          ReferenceBinding superClass = x.binding.declaringClass;
          boolean nestedSuper = JdtUtil.isInnerClass(superClass);
          if (nestedSuper) {
            processSuperCallThisArgs(superClass, call, qualifier, x.qualification);
          }
          call.addArgs(callArgs);
          if (nestedSuper) {
            processSuperCallLocalArgs(superClass, call);
          }
        } else {
          assert (x.qualification == null);
          ReferenceBinding declaringClass = x.binding.declaringClass;
          boolean nested = JdtUtil.isInnerClass(declaringClass);
          if (nested) {
            processThisCallThisArgs(declaringClass, call);
          }
          call.addArgs(callArgs);
          if (nested) {
            processThisCallLocalArgs(declaringClass, call);
          }
        }
        call.setStaticDispatchOnly();
        push(call.makeStatement());
      } catch (Throwable e) {
        throw translateException(x, e);
      } finally {
        scope.methodScope().isConstructorCall = false;
      }
    }

    @Override
    public void endVisit(ExtendedStringLiteral x, BlockScope scope) {
      endVisit((StringLiteral) x, scope);
    }

    @Override
    public void endVisit(FalseLiteral x, BlockScope scope) {
      push(JBooleanLiteral.FALSE);
    }

    @Override
    public void endVisit(FieldDeclaration x, MethodScope scope) {
      try {
        JExpression initialization = pop(x.initialization);
        JField field = typeMap.get(x.binding);
        if (field instanceof JEnumField) {
          // An enum field must be initialized!
          assert (initialization instanceof JNewInstance);
        }

        if (initialization != null) {
          SourceInfo info = makeSourceInfo(x);
          JExpression instance = null;
          if (!x.isStatic()) {
            instance = makeThisRef(info);
          }
          // JDeclarationStatement's ctor sets up the field's initializer.
          JStatement decl =
              new JDeclarationStatement(info, new JFieldRef(info, instance, field, curClass.type),
                  initialization);
          // will either be init or clinit
          curMethod.body.getBlock().addStmt(decl);
        }
        popMethodInfo();
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(FieldReference x, BlockScope scope) {
      try {
        FieldBinding fieldBinding = x.binding;
        SourceInfo info = makeSourceInfo(x);
        JExpression instance = pop(x.receiver);
        JExpression expr = createFieldRef(instance, info, fieldBinding);
        if (x.genericCast != null) {
          JType[] castTypes = processCastType(x.genericCast);
          /*
           * Note, this may result in an invalid AST due to an LHS cast
           * operation. We fix this up in FixAssignmentsToUnboxOrCast.
           */
          expr = maybeCast(castTypes, expr);
        }
        push(expr);
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(FloatLiteral x, BlockScope scope) {
      try {
        push(JFloatLiteral.get(x.constant.floatValue()));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(ForeachStatement x, BlockScope scope) {
      SourceInfo info = makeSourceInfo(x);

      JBlock body = popBlock(info, x.action);
      JExpression collection = pop(x.collection);
      JDeclarationStatement elementDecl = pop(x.elementVariable);
      assert (elementDecl.initializer == null);

      JLocal elementVar = (JLocal) curMethod.locals.get(x.elementVariable.binding);
      String elementVarName = elementVar.getName();

      JForStatement result;
      if (x.collectionVariable != null) {
        /**
         * <pre>
       * for (final T[] i$array = collection,
       *          int i$index = 0,
       *          final int i$max = i$array.length;
       *      i$index < i$max; ++i$index) {
       *   T elementVar = i$array[i$index];
       *   // user action
       * }
       * </pre>
         */
        JLocal arrayVar = JProgram.createLocal(info, elementVarName + "$array",
            typeMap.get(x.collection.resolvedType), true, curMethod.body);
        JLocal indexVar =
            JProgram.createLocal(info, elementVarName + "$index", JPrimitiveType.INT, false,
                curMethod.body);
        JLocal maxVar =
            JProgram.createLocal(info, elementVarName + "$max", JPrimitiveType.INT, true,
                curMethod.body);

        List<JStatement> initializers = Lists.newArrayListWithCapacity(3);
        // T[] i$array = arr
        initializers.add(makeDeclaration(info, arrayVar, collection));
        // int i$index = 0
        initializers.add(makeDeclaration(info, indexVar, JIntLiteral.get(0)));
        // int i$max = i$array.length
        initializers.add(makeDeclaration(info, maxVar,
            new JArrayLength(info, arrayVar.makeRef(info))));

        // i$index < i$max
        JExpression condition =
            new JBinaryOperation(info, JPrimitiveType.BOOLEAN, JBinaryOperator.LT,
                indexVar.makeRef(info), maxVar.makeRef(info));

        // ++i$index
        JExpression increments = new JPrefixOperation(info, JUnaryOperator.INC,
            indexVar.makeRef(info));

        // T elementVar = i$array[i$index];
        elementDecl.initializer =
            new JArrayRef(info, arrayVar.makeRef(info), indexVar.makeRef(info));
        body.addStmt(0, elementDecl);

        result = new JForStatement(info, initializers, condition, increments, body);
      } else {
        /**
         * <pre>
         * for (Iterator&lt;T&gt; i$iterator = collection.iterator(); i$iterator.hasNext();) {
         *   T elementVar = i$iterator.next();
         *   // user action
         * }
         * </pre>
         */
        CompilationUnitScope cudScope = scope.compilationUnitScope();
        ReferenceBinding javaUtilIterator = scope.getJavaUtilIterator();
        ReferenceBinding javaLangIterable = scope.getJavaLangIterable();
        MethodBinding iterator = javaLangIterable.getExactMethod(ITERATOR_, NO_TYPES, cudScope);
        MethodBinding hasNext = javaUtilIterator.getExactMethod(HAS_NEXT_, NO_TYPES, cudScope);
        MethodBinding next = javaUtilIterator.getExactMethod(NEXT_, NO_TYPES, cudScope);
        JLocal iteratorVar =
            JProgram.createLocal(info, (elementVarName + "$iterator"), typeMap
                .get(javaUtilIterator), false, curMethod.body);

        List<JStatement> initializers = Lists.newArrayListWithCapacity(1);
        // Iterator<T> i$iterator = collection.iterator()
        initializers.add(makeDeclaration(info, iteratorVar, new JMethodCall(info, collection,
            typeMap.get(iterator))));

        // i$iterator.hasNext()
        JExpression condition =
            new JMethodCall(info, iteratorVar.makeRef(info), typeMap.get(hasNext));

        // T elementVar = (T) i$iterator.next();
        elementDecl.initializer =
            new JMethodCall(info, iteratorVar.makeRef(info), typeMap.get(next));

        // Perform any implicit reference type casts (due to generics).
        // Note this occurs before potential unboxing.
        if (elementVar.getType() != javaLangObject) {
          TypeBinding collectionElementType = getCollectionElementTypeBinding(x);
          JType toType = typeMap.get(collectionElementType);
          assert (toType instanceof JReferenceType);
          elementDecl.initializer = maybeCast(toType, elementDecl.initializer);
        }

        body.addStmt(0, elementDecl);

        result = new JForStatement(info, initializers, condition,
            null, body);
      }

      // May need to box or unbox the element assignment.
      elementDecl.initializer =
          maybeBoxOrUnbox(elementDecl.initializer, x.elementVariableImplicitWidening);
      push(result);
    }

    @Override
    public void endVisit(ForStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JStatement action = pop(x.action);

        // JDT represents the 3rd for component (increments) as a list of statements. These
        // statements are always expression statements as per JLS 14.14.1
        // Here the List<JExpressionStatement> is transformed into a more adequate List<Expression>.
        List<JExpression> incrementsExpressions = Lists.transform(pop(x.increments),
            new Function<JStatement, JExpression>() {
              @Override
              public JExpression apply(JStatement statement) {
                Preconditions.checkArgument(statement instanceof JExpressionStatement);
                return ((JExpressionStatement) statement).getExpr();
              }
            });

        // And turned into a single expression (possibly null if empty).
        JExpression incrementsExpression =
            singleExpressionFromExpressionList(info, incrementsExpressions);

        JExpression condition = pop(x.condition);
        List<JStatement> initializations = pop(x.initializations);
        push(new JForStatement(info, initializations, condition, incrementsExpression, action));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(IfStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JStatement elseStatement = pop(x.elseStatement);
        JStatement thenStatement = pop(x.thenStatement);
        JExpression condition = pop(x.condition);
        push(new JIfStatement(info, condition, thenStatement, elseStatement));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(Initializer x, MethodScope scope) {
      try {
        JBlock block = pop(x.block);
        if (block != null) {
          curMethod.body.getBlock().addStmt(block);
        }
        popMethodInfo();
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(InstanceOfExpression x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JExpression expr = pop(x.expression);
        JReferenceType testType = (JReferenceType) typeMap.get(x.type.resolvedType);
        push(new JInstanceOf(info, testType, expr));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(IntLiteral x, BlockScope scope) {
      try {
        push(JIntLiteral.get(x.constant.intValue()));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(LabeledStatement x, BlockScope scope) {
      try {
        JStatement statement = pop(x.statement);
        if (statement == null) {
          push(null);
          return;
        }
        SourceInfo info = makeSourceInfo(x);
        push(new JLabeledStatement(info, getOrCreateLabel(info, x.label), statement));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public boolean visit(ReferenceExpression x, BlockScope blockScope) {
      // T[][][]::new => lambda$n(int x) { return new T[int x][][]; }
      if (x.isArrayConstructorReference()) {
        // ensure array[]::new synthetic method (created by JDT) has an associated JMethod
        JMethod synthMethod = typeMap.get(x.binding);
        if (synthMethod.getBody() == null) {
          JMethodBody body = new JMethodBody(synthMethod.getSourceInfo());
          List<JExpression> dims = new ArrayList<JExpression>();
          JArrayType arrayType = (JArrayType) synthMethod.getType();
          JParameter dimParam = synthMethod.getParams().get(0);
          JExpression dimArgExpr = dimParam.makeRef(dimParam.getSourceInfo());
          dims.add(dimArgExpr);
          JNewArray newArray = JNewArray.createArrayWithDimensionExpressions(
              synthMethod.getSourceInfo(), arrayType, dims);
          body.getBlock().addStmt(newArray.makeReturnStatement());
          synthMethod.setBody(body);
        }
      }

      if (hasQualifier(x)) {
        x.lhs.traverse(this, blockScope);
      }
      return false;
    }

    @Override
    public boolean visit(LambdaExpression x, BlockScope blockScope) {
      // Fetch the variables 'captured' by this lambda
      SyntheticArgumentBinding[] synthArgs = x.outerLocalVariables;
      // Get the parameter names, captured locals + lambda arguments
      String paramNames[] = computeCombinedParamNames(x, synthArgs);
      SourceInfo info = makeSourceInfo(x);
      // JDT synthesizes a method lambda$n(capture1, capture2, ..., lambda_arg1, lambda_arg2, ...)
      // Here we create a JMethod from this
      JMethod lambdaMethod = createMethodFromBinding(info, x.binding, paramNames);
      // Because the lambda implementations is synthesized as a static method in the
      // enclosing class, it needs to be adjusted if that class happens to be a JsType.
      lambdaMethod.setJsMemberInfo(HasJsInfo.JsMemberType.NONE, null, null, false);
      if (curClass.type.isJsNative()) {
        lambdaMethod.setJsOverlay();
      }
      JMethodBody methodBody = new JMethodBody(info);
      lambdaMethod.setBody(methodBody);
      // We need to push this method  on the stack as it introduces a scope, and
      // expressions in the body need to lookup variable refs like parameters from it
      pushMethodInfo(new MethodInfo(lambdaMethod, methodBody, x.scope));
      pushLambdaExpressionLocalsIntoMethodScope(x, synthArgs, lambdaMethod);
      // now the body of the lambda is processed
      return true;
    }

    private void pushLambdaExpressionLocalsIntoMethodScope(LambdaExpression x,
        SyntheticArgumentBinding[] syntheticArguments, JMethod lambdaMethod) {
      Iterator<JParameter> it = lambdaMethod.getParams().iterator();
      if (syntheticArguments != null) {
        MethodScope scope = x.getScope();
        for (SyntheticArgumentBinding sa : syntheticArguments) {
          VariableBinding[] path = scope.getEmulationPath(sa.actualOuterLocalVariable);
          assert path.length == 1 && path[0] instanceof LocalVariableBinding;
          JParameter param = it.next();
          curMethod.locals.put((LocalVariableBinding) path[0], param);
        }
        for (Argument a : x.arguments) {
          curMethod.locals.put(a.binding, it.next());
        }
      }
    }

    /**
     * Calculate the names of all the parameters a lambda method will need, that is, the
     * combination of all captured locals plus all arguments to the lambda expression.
     */
    private String[] computeCombinedParamNames(LambdaExpression x,
        SyntheticArgumentBinding[] syntheticArguments) {
      String[] paramNames;
      paramNames = new String[x.binding.parameters.length];
      int numSynthArgs = syntheticArguments != null ? syntheticArguments.length : 0;
      for (int i = 0; i < paramNames.length; i++) {
        if (i < numSynthArgs) {
          paramNames[i] = nameForSyntheticArgument(syntheticArguments[i]);
        } else {
          paramNames[i] = nameForArgument(x.arguments, i - numSynthArgs, i);
        }
      }
      return paramNames;
    }

    private String nameForArgument(Argument[] arguments, int argIndex, int argPosition) {
      return new String(arguments[argIndex].name) + "_" + argPosition;
    }

    private String nameForSyntheticArgument(SyntheticArgumentBinding synthArg) {
      return synthArg.actualOuterLocalVariable != null ?
          intern(intern(synthArg.actualOuterLocalVariable.name) + "_" + synthArg.resolvedPosition) :
          intern(synthArg.name);
    }

    @Override
    public void endVisit(LambdaExpression x, BlockScope blockScope) {

      /**
       * Our output of a (args) -> expression_using_locals(locals) looks like this.
       *
       * class Enclosing {
       *
       *   T lambda$0(locals, args) {...lambda expr }
       *
       *   class lambda$0$type implements I {
       *       ctor([outer], locals) { ... }
       *       R <SAM lambdaMethod>(args) { return [outer].lambda$0(locals, args); }
       *   }
       * }
       *
       * And replaces the lambda with new lambda$0$Type([outer this], captured locals...).
       */

      // The target accepting this lambda is looking for which type? (e.g. ClickHandler, Runnable)
      TypeBinding binding = x.expectedType();
      // Find the single abstract method of this interface
      MethodBinding samBinding = binding.getSingleAbstractMethod(blockScope, false);
      assert (samBinding != null && samBinding.isValidBinding());

      // Lookup the JMethod version
      JMethod interfaceMethod = typeMap.get(samBinding);
      // And its JInterface container we must implement
      // There may be more than more JInterface containers to be implemented
      // if the lambda expression is cast to a IntersectionCastType.
      JInterfaceType[] funcType;
      if (binding instanceof IntersectionTypeBinding18) {
        funcType = processIntersectionTypeForLambda((IntersectionTypeBinding18) binding, blockScope,
            JdtUtil.signature(samBinding));
      } else {
        funcType = new JInterfaceType[] {(JInterfaceType) typeMap.get(binding)};
      }
      SourceInfo info = makeSourceInfo(x);

      // Create an inner class to implement the interface and SAM method.
      // class lambda$0$Type implements T {}

      String innerLambdaImplementationClassShortName = String.valueOf(x.binding.selector);
      JClassType innerLambdaClass = createInnerClass(
          curClass.getClassOrInterface(), innerLambdaImplementationClassShortName, info, funcType);
      JConstructor ctor = new JConstructor(info, innerLambdaClass, AccessModifier.PRIVATE);

      // locals captured by the lambda and saved as fields on the anonymous inner class
      List<JField> locals = new ArrayList<JField>();
      SyntheticArgumentBinding[] synthArgs = x.outerLocalVariables;

      // create the constructor for the anonymous inner and return the field used to store the
      // enclosing 'this' which is needed by the SAM method implementation later
      JField outerField =
          createLambdaConstructor(x, info, innerLambdaClass, ctor, locals, synthArgs);

      // the method containing the lambda expression that the anonymous inner class delegates to,
      // it corresponds directly to the lambda expression itself, produced by JDT as a helper method
      JMethod lambdaMethod = createLambdaMethod(x);

      // Now that we've added an implementation method for the lambda, we must create the inner
      // class method that implements the target interface type that delegates to the target lambda
      // method
      JMethod samMethod = new JMethod(info, interfaceMethod.getName(), innerLambdaClass,
          interfaceMethod.getType(), false, false, true, interfaceMethod.getAccess());

      // implements the SAM, e.g. Callback.onCallback(), Runnable.run(), etc
      createLambdaSamMethod(x, interfaceMethod, info, innerLambdaClass, locals, outerField,
          lambdaMethod,
          samMethod);

      ctor.freezeParamTypes();
      samMethod.freezeParamTypes();

      // Create necessary bridges.
      createFunctionalExpressionBridges(innerLambdaClass, x, samMethod);

      // replace (x,y,z) -> expr with 'new Lambda(args)'
      replaceLambdaWithInnerClassAllocation(x, info, innerLambdaClass, ctor, synthArgs);
      popMethodInfo();
      // Add the newly generated type
      newTypes.add(innerLambdaClass);
    }

    private void createFunctionalExpressionBridges(
        JClassType functionalExpressionImplementationClass,
        FunctionalExpression functionalExpression,
        JMethod functionalInterfaceAbstractMethod) {
      if (functionalExpression.getRequiredBridges() != null) {
        for (MethodBinding methodBinding : functionalExpression.getRequiredBridges()) {
          // Create bridges.
          createBridgeMethod(functionalExpressionImplementationClass, methodBinding,
              functionalInterfaceAbstractMethod);
        }
      }
    }

    private void createLambdaSamMethod(LambdaExpression x, JMethod interfaceMethod, SourceInfo info,
        JClassType innerLambdaClass, List<JField> locals, JField outerField, JMethod lambdaMethod,
        JMethod samMethod) {
      // The parameters to this method will be the same as the Java interface that must be
      // implemented
      for (JParameter origParam : interfaceMethod.getParams()) {
        samMethod.cloneParameter(origParam);
      }
      // Create a body like void onClick(ClickEvent e) { OuterClass.lambdaMethod(locals, e); }
      JMethodBody samMethodBody = new JMethodBody(info);
      // First we create the method call to the outer lambda method
      JMethodCall samCall = new JMethodCall(info, x.shouldCaptureInstance ?
          new JFieldRef(info, new JThisRef(info, innerLambdaClass), outerField, innerLambdaClass) :
          null, lambdaMethod);

      // and add any locals that were storing captured outer variables as arguments to the call
      // first
      for (JField localField : locals) {
        samCall.addArg(new JFieldRef(info, new JThisRef(info, innerLambdaClass),
            localField, innerLambdaClass));
      }

      // and now we propagate the rest of the actual interface method parameters on the end
      // (e.g. ClickEvent e)
      for (JParameter param : samMethod.getParams()) {
        samCall.addArg(param.makeRef(info));
      }

      // we either add a return statement, or don't, depending on what the interface wants
      samMethodBody.getBlock().addStmt(
          JjsUtils.makeMethodEndStatement(samMethod.getType(), samCall));

      samMethod.setBody(samMethodBody);
      innerLambdaClass.addMethod(samMethod);
    }

    private JField createLambdaConstructor(LambdaExpression x, SourceInfo info,
        JClassType innerLambdaClass, JConstructor ctor, List<JField> locals,
        SyntheticArgumentBinding[] synthArgs) {
      // Create a constructor to accept all "captured" locals
      // CTor([OuterClassRef ref], capture1, capture2) { }
      JMethodBody ctorBody = new JMethodBody(info);
      JField outerField = null;
      // if this lambda refers to fields on the enclosing instance
      if (x.shouldCaptureInstance) {
        // ctor($$outer) { this.$$outer = $$outer; }
        outerField = createAndBindCapturedLambdaParameter(info, OUTER_LAMBDA_PARAM_NAME,
            innerLambdaClass.getEnclosingType(),
            ctor, ctorBody);
      }

      // Now we add parameters to the ctor
      // this is the outer instance (if needed), plus any method local variables captured
      String paramNames[] = new String[x.binding.parameters.length];
      int numSynthArgs = synthArgs != null ? synthArgs.length : 0;

      for (int i = 0; i < paramNames.length; i++) {
        // Setup params, fields, and ctor assignments for the outer captured vars
        if (i < numSynthArgs) {
          paramNames[i] = nameForSyntheticArgument(synthArgs[i]);
          JType captureType = typeMap.get(synthArgs[i].type);
          // adds ctor(..., param, ...) { ...this.param = param }
          JField captureField = createAndBindCapturedLambdaParameter(
              info, paramNames[i], captureType, ctor, ctorBody);
          locals.add(captureField);
        } else {
          // Record the names of the actual closure arguments,
          // e.g. (ClickEvent x) -> expr will be 'x'
          paramNames[i] = nameForArgument(x.arguments, i - numSynthArgs, i);
        }
      }

      ctor.setBody(ctorBody);
      innerLambdaClass.addMethod(ctor);
      return outerField;
    }

    private JMethod createLambdaMethod(LambdaExpression x) {
      // First let's get that synthetic method we created in the visit() call on the
      // containing class?
      JMethod lambdaMethod = curMethod.method;
      // And pop off the body nodes of the LambdaExpression that was processed as children
      // Deal with any boxing/unboxing needed
      JNode node = pop();
      if (node instanceof JExpression) {
        node = maybeBoxOrUnbox((JExpression) node, (Expression) x.body);
      }

      JMethodBody body = (JMethodBody) curMethod.method.getBody();
      // and copy those nodes into the body of our synthetic method
      JStatement lambdaStatement = getOrCreateLambdaStatement(node);
      body.getBlock().addStmt(lambdaStatement);
      lambdaMethod.setBody(body);
      return lambdaMethod;
    }

    private void replaceLambdaWithInnerClassAllocation(LambdaExpression x, final SourceInfo info,
        JClassType innerLambdaClass, JConstructor ctor, SyntheticArgumentBinding[] synthArgs) {
      // Finally, we replace the LambdaExpression with
      // new InnerLambdaClass(this, local1, local2, ...);
      assert ctor.getEnclosingType() == innerLambdaClass;
      JNewInstance allocLambda = new JNewInstance(info, ctor);
      // only pass 'this' if lambda refers to fields on outer class
      if (x.shouldCaptureInstance) {
        allocLambda.addArg(new JThisRef(info, innerLambdaClass.getEnclosingType()));
      }
      for (final SyntheticArgumentBinding sa : synthArgs) {
        final MethodInfo method = methodStack.peek();
        JExpression capturedLocalReference = null;
        // Find the local variable in the current method context that is referred by the inner
        // lambda.
        LocalVariableBinding localVariable = FluentIterable.from(method.locals.keySet()).firstMatch(
            new Predicate<LocalVariableBinding>() {
              @Override
              public boolean apply(LocalVariableBinding enclosingLocal) {
                // Either the inner lambda refers directly to the enclosing scope variable, or
                // it is a capture from an enclosing scope, in which case both synthetic
                // arguments point to the same outer local variable.
                return enclosingLocal == sa.actualOuterLocalVariable
                    || (enclosingLocal instanceof SyntheticArgumentBinding)
                        && ((SyntheticArgumentBinding) enclosingLocal).actualOuterLocalVariable == 
                          sa.actualOuterLocalVariable;
              }
            }).orNull();
        if (localVariable != null) {
          // lambda is capturing a local from the immediate context
          capturedLocalReference = makeLocalRef(info, localVariable, method);
        } else {
          // Local variable not found in current method context. Trying to find corresponding
          // synthetic field in case if lambda is placed in anonymous/local class
          // e.g. { int x = 1; new Outer(){ void m (){ Lambda l = () -> x+1;} }; }
          Entry<SyntheticArgumentBinding, JField> capturedLocalInOuterClass = FluentIterable.from(
              curClass.syntheticFields.entrySet()).firstMatch(
                  new Predicate<Entry<SyntheticArgumentBinding, JField>>() {
                    @Override
                    public boolean apply(Entry<SyntheticArgumentBinding, JField> entry) {
                      return entry.getKey().actualOuterLocalVariable == sa.actualOuterLocalVariable;
                    }
                  }).orNull();
          if (capturedLocalInOuterClass != null) {
            // local from outer scope has already been captured by enclosing class.
            capturedLocalReference = makeInstanceFieldRef(info, capturedLocalInOuterClass
                .getValue());
          }
        }

        assert capturedLocalReference != null;
        allocLambda.addArg(capturedLocalReference);
      }

      // put the result on the stack, and pop out synthetic method from the scope
      push(allocLambda);
    }

    private JField createAndBindCapturedLambdaParameter(SourceInfo info,
        String paramName, JType captureType,
        JConstructor ctor, JMethodBody ctorBody) {
      JField paramField;
      JParameter param = createLambdaParameter(info, paramName, captureType, ctor);

      // Plus a field to store it
      paramField = createLambdaField(info, paramName, captureType, ctor.getEnclosingType());

      // Now add the initializers to bind the param to field
      // this.paramField = param
      JThisRef thisRef = new JThisRef(info, ctor.getEnclosingType());
      JFieldRef paramFieldRef = new JFieldRef(info, thisRef, paramField, ctor.getEnclosingType());
      JParameterRef paramRef = param.makeRef(info);
      ctorBody.getBlock().addStmt(
          new JBinaryOperation(info, paramFieldRef.getType(),
              JBinaryOperator.ASG,
              paramFieldRef, paramRef).makeStatement());
      return paramField;
    }

    private JField createLambdaField(SourceInfo info, String fieldName, JType fieldType,
        JClassType enclosingType) {
      JField outerField;
      outerField = new JField(info, fieldName, enclosingType, fieldType, false, Disposition.NONE,
          AccessModifier.PRIVATE);
      enclosingType.addField(outerField);
      return outerField;
    }

    private JParameter createLambdaParameter(SourceInfo info, String paramName, JType paramType,
        JConstructor ctor) {
      return ctor.createFinalParameter(info, paramName, paramType);
    }

    private JClassType createInnerClass(JDeclaredType enclosingType, String shortNname,
        SourceInfo info, JInterfaceType... superInterfaces) {
      JClassType innerLambdaClass = new JClassType(info,
          Joiner.on('$').join(enclosingType.getName(), shortNname, "Type"), false, true);
      innerLambdaClass.setEnclosingType(enclosingType);
      for (JInterfaceType type : superInterfaces) {
        innerLambdaClass.addImplements(type);
      }
      innerLambdaClass.setSuperClass(javaLangObject);

      createSyntheticMethod(info, CLINIT_METHOD_NAME, innerLambdaClass, JPrimitiveType.VOID, false,
          true, true, AccessModifier.PRIVATE);

      createSyntheticMethod(info, INIT_NAME_METHOD_NAME, innerLambdaClass, JPrimitiveType.VOID,
          false, false, true, AccessModifier.PRIVATE);

      // Add a getClass() implementation for all non-Object classes.
      createSyntheticMethod(info, GwtAstBuilder.GET_CLASS_METHOD_NAME, innerLambdaClass,
          javaLangClass, false, false, false, AccessModifier.PUBLIC,
          new JClassLiteral(info, innerLambdaClass).makeReturnStatement());

      innerLambdaClass.setClassDisposition(JDeclaredType.NestedClassDisposition.LAMBDA);
      return innerLambdaClass;
    }

      @Override
    public void endVisit(LocalDeclaration x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JLocal local = (JLocal) curMethod.locals.get(x.binding);
        assert local != null;
        JLocalRef localRef = local.makeRef(info);
        JExpression initialization = pop(x.initialization);
        push(new JDeclarationStatement(info, localRef, initialization));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(LongLiteral x, BlockScope scope) {
      try {
        push(JLongLiteral.get(x.constant.longValue()));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(MessageSend x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JMethod method = typeMap.get(x.binding);

        List<JExpression> arguments = popCallArguments(info, x.arguments, x.binding);
        JExpression receiver = pop(x.receiver);
        if (x.receiver instanceof ThisReference) {
          if (method.isStatic()) {
            // don't bother qualifying it, it's a no-op
            receiver = null;
          } else if ((x.bits & ASTNode.DepthMASK) != 0) {
            // outer method can be reached through emulation if implicit access
            ReferenceBinding targetType =
                scope.enclosingSourceType().enclosingTypeAt(
                    (x.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
            receiver = resolveThisReference(info, targetType, true, scope);
          } else if (x.receiver.sourceStart == 0) {
            // Synthetic this ref with bad source info; fix the info.
            JThisRef oldRef = (JThisRef) receiver;
            receiver = new JThisRef(info, oldRef.getClassType());
          }
        }

        JMethodCall methodCall = new JMethodCall(info, receiver, method);

        // On a super ref, don't allow polymorphic dispatch. Oddly enough,
        // QualifiedSuperReference not derived from SuperReference!
        boolean isSuperRef =
            x.receiver instanceof SuperReference || x.receiver instanceof QualifiedSuperReference;
        if (isSuperRef) {
          methodCall.setStaticDispatchOnly();
        }

        // The arguments come first.
        methodCall.addArgs(arguments);

        if (x.valueCast != null) {
          JType[] targetTypes = processCastType(x.valueCast);
          push(isUncheckedGenericMethodCall(x)
              ? maybeInsertUnsafeTypeCoercion(targetTypes[0], methodCall)
              : maybeCast(targetTypes, methodCall));
        } else {
          push(methodCall);
        }
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(MethodDeclaration x, ClassScope scope) {
      try {
        if (x.isNative()) {
          processNativeMethod(x);
        } else {
          List<JStatement> statements = pop(x.statements);
          curMethod.body.getBlock().addStmts(statements);
        }
        popMethodInfo();
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(NullLiteral x, BlockScope scope) {
      push(JNullLiteral.INSTANCE);
    }

    @Override
    public void endVisit(OR_OR_Expression x, BlockScope scope) {
      pushBinaryOp(x, JBinaryOperator.OR);
    }

    @Override
    public void endVisit(PostfixExpression x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JUnaryOperator op;
        switch (x.operator) {
          case OperatorIds.MINUS:
            op = JUnaryOperator.DEC;
            break;

          case OperatorIds.PLUS:
            op = JUnaryOperator.INC;
            break;

          default:
            throw new InternalCompilerException("Unexpected postfix operator");
        }

        JExpression lhs = pop(x.lhs);
        push(new JPostfixOperation(info, op, lhs));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(PrefixExpression x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JUnaryOperator op;
        switch (x.operator) {
          case OperatorIds.MINUS:
            op = JUnaryOperator.DEC;
            break;

          case OperatorIds.PLUS:
            op = JUnaryOperator.INC;
            break;

          default:
            throw new InternalCompilerException("Unexpected prefix operator");
        }

        JExpression lhs = pop(x.lhs);
        push(new JPrefixOperation(info, op, lhs));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(QualifiedAllocationExpression x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        List<JExpression> arguments = popCallArguments(info, x.arguments, x.binding);
        pushNewExpression(info, x, x.enclosingInstance(), arguments, scope);
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(QualifiedNameReference x, BlockScope scope) {
      try {
        JExpression curRef = resolveNameReference(x, scope);
        if (curRef == null) {
          push(null);
          return;
        }
        if (x.genericCast != null) {
          JType castType = typeMap.get(x.genericCast);
          curRef = maybeCast(castType, curRef);
        }
        SourceInfo info = curRef.getSourceInfo();

        /*
         * JDT represents multiple field access as an array of fields, each
         * qualified by everything to the left. So each subsequent item in
         * otherBindings takes the current expression as a qualifier.
         */
        if (x.otherBindings != null) {
          for (int i = 0; i < x.otherBindings.length; ++i) {
            FieldBinding fieldBinding = x.otherBindings[i];
            curRef = createFieldRef(curRef, info, fieldBinding);
            if (x.otherGenericCasts != null && x.otherGenericCasts[i] != null) {
              JType castType = typeMap.get(x.otherGenericCasts[i]);
              curRef = maybeCast(castType, curRef);
            }
          }
        }
        push(curRef);
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    private JExpression createFieldRef(JExpression instance, SourceInfo info,
        FieldBinding fieldBinding) {
      if (fieldBinding.declaringClass == null) {
        // probably array.length
        if (!LENGTH_FIELD_NAME.equals(String.valueOf(fieldBinding.name))) {
          throw new InternalCompilerException("Expected [array].length.");
        }
        instance = new JArrayLength(info, instance);
      } else {
        JField field = typeMap.get(fieldBinding);
        instance = new JFieldRef(info, instance, field, curClass.type);
      }
      return instance;
    }

    @Override
    public void endVisit(QualifiedSuperReference x, BlockScope scope) {
      try {
        // Oddly enough, super refs can be modeled as this refs, because
        // whatever expression they qualify has already been resolved.
        SourceInfo info = makeSourceInfo(x);
        ReferenceBinding targetType = (ReferenceBinding) x.qualification.resolvedType.erasure();
        if (targetType.isInterface()) {
          // Java8 super reference to default method from subtype, X.super.someDefaultMethod
          push(makeThisRef(info));
        } else {
          push(resolveThisReference(info, targetType, true, scope));
        }
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(QualifiedThisReference x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        ReferenceBinding targetType = (ReferenceBinding) x.qualification.resolvedType;
        push(resolveThisReference(info, targetType, true, scope));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    private int nextReferenceExpressionId = 0;

    @Override
    public void endVisit(ReferenceExpression x, BlockScope blockScope) {
      /**
       * Converts an expression like foo(qualifier::someMethod) into
       *
       * class Enclosing {
       *
       *   [static] T someMethod(locals, args) {...lambda expr }
       *
       *   class lambda$someMethodType implements I {
       *       ctor([qualifier]) { ... }
       *       R <SAM lambdaMethod>(args) { return [outer]someMethod(args); }
       *   }
       * }
       *
       * and replaces qualifier::someMethod with new lambda$someMethodType([outer this])
       *
       * [x] denotes optional, depending on context of whether outer this scope is needed.
       */

      // Resolve the reference expression to make sure the declaring class of the method is resolved
      // to the right type.
      x.resolve(blockScope);
      // Calculate what type this reference is going to bind to, and what single abstract method
      TypeBinding binding = x.expectedType();
      MethodBinding samBinding = binding.getSingleAbstractMethod(blockScope, false);
      MethodBinding declarationSamBinding =
          binding.getSingleAbstractMethod(blockScope, false).original();
      // Get the interface method is binds to
      JMethod interfaceMethod = typeMap.get(declarationSamBinding);
      JInterfaceType funcType = (JInterfaceType) typeMap.get(binding);
      SourceInfo info = makeSourceInfo(x);

      // Get the method that the Type::method is actually referring to
      MethodBinding referredMethodBinding = x.binding;
      if (referredMethodBinding instanceof SyntheticMethodBinding) {
        SyntheticMethodBinding synthRefMethodBinding =
            (SyntheticMethodBinding) referredMethodBinding;
        if (synthRefMethodBinding.targetMethod != null) {
          // generated in cases were a private method in an outer class needed to be called
          // e.g. outer.access$0 calls some outer.private_method
          referredMethodBinding = synthRefMethodBinding.targetMethod;
          // privateCtor::new generates overloaded <init> references with fake args that delegate
          // to the real ctor (JDT WTF!). Will we ever need to go deeper?
          if (synthRefMethodBinding.fakePaddedParameters != 0
              && synthRefMethodBinding.targetMethod instanceof SyntheticMethodBinding) {
            referredMethodBinding = ((SyntheticMethodBinding) referredMethodBinding).targetMethod;
          }
        }
      }
      JMethod referredMethod = typeMap.get(referredMethodBinding);
      boolean hasQualifier = hasQualifier(x);

      // Constructors, overloading and generics means that the safest approach is to consider
      // each different member reference as a different lambda implementation.
      String lambdaImplementationClassShortName =
          String.valueOf(nextReferenceExpressionId++) + "methodref$"
              + (x.binding.isConstructor() ? "ctor" : String.valueOf(x.binding.selector));
      List<JExpression> enclosingThisRefs = Lists.newArrayList();

      // Create an inner class to hold the implementation of the interface
      JClassType innerLambdaClass = createInnerClass(
          curClass.getClassOrInterface(), lambdaImplementationClassShortName, info, funcType);
      newTypes.add(innerLambdaClass);

      JConstructor ctor = new JConstructor(info, innerLambdaClass, AccessModifier.PRIVATE);

      JMethodBody ctorBody = new JMethodBody(info);
      JThisRef thisRef = new JThisRef(info, innerLambdaClass);
      JExpression instance = null;

      List<JField> enclosingInstanceFields = new ArrayList<JField>();
      // If we have a qualifier instance, we have to stash it in the constructor
      if (hasQualifier) {
        // this.$$outer = $$outer
        JField outerField = createAndBindCapturedLambdaParameter(info, OUTER_LAMBDA_PARAM_NAME,
            referredMethod.getEnclosingType(), ctor, ctorBody);
        instance = new JFieldRef(info,
            new JThisRef(info, innerLambdaClass), outerField, innerLambdaClass);
      } else if (referredMethod instanceof JConstructor) {
        // the method we are invoking is a constructor and may need enclosing instances passed to
        // it.
        // For example, an class Foo { class Inner { Inner(int x) { } } } needs
        // it's constructor invoked with an enclosing instance, Inner::new
        // Java8 doesn't allow the qualifified case, e.g. x.new Foo() -> x.Foo::new
        ReferenceBinding targetBinding = referredMethodBinding.declaringClass;
        if (targetBinding.syntheticEnclosingInstanceTypes() != null) {
          for (ReferenceBinding argType : targetBinding.syntheticEnclosingInstanceTypes()) {
            argType = (ReferenceBinding) argType.erasure();
            JExpression enclosingThisRef = resolveThisReference(info, argType, false, blockScope);
            JField enclosingInstance = createAndBindCapturedLambdaParameter(info,
                String.valueOf(argType.readableName()).replace('.', '_'),
                enclosingThisRef.getType(), ctor, ctorBody);
            enclosingInstanceFields.add(enclosingInstance);
            enclosingThisRefs.add(enclosingThisRef);
          }
        }
      }
      ctor.setBody(ctorBody);
      innerLambdaClass.addMethod(ctor);

      // Create an implementation of the target interface that invokes the method referred to
      // void onClick(ClickEvent e) { outer.referredMethod(e); }
      JMethod samMethod = new JMethod(info, interfaceMethod.getName(),
          innerLambdaClass, interfaceMethod.getType(),
          false, false, true, interfaceMethod.getAccess());
      for (JParameter origParam : interfaceMethod.getParams()) {
        samMethod.cloneParameter(origParam);
      }
      JMethodBody samMethodBody = new JMethodBody(info);

      Iterator<JParameter> paramIt = samMethod.getParams().iterator();
      // here's where it gets tricky. A method can have an implicit qualifier, e.g.
      // String::compareToIgnoreCase, it's non-static, it only has one argument, but it binds to
      // Comparator<T>.
      // The first argument serves as the qualifier, so for example, the method dispatch looks
      // like this: int compare(T a, T b) { a.compareTo(b); }
      if (!hasQualifier
          && !referredMethod.isStatic()
          && !referredMethod.isConstructor()
          && instance == null) {
        // the instance qualifier is the first parameter in this case.
        // Needs to be cast the actual type due to generics.
        instance = new JCastOperation(info, typeMap.get(referredMethodBinding.declaringClass),
            paramIt.next().makeRef(info));
      }
      JMethodCall samCall = null;

      if (referredMethod.isConstructor()) {
        // Constructors must be invoked with JNewInstance
        samCall = new JNewInstance(info, (JConstructor) referredMethod);
        for (JField enclosingInstance : enclosingInstanceFields) {
          samCall.addArg(new JFieldRef(enclosingInstance.getSourceInfo(), thisRef,
              enclosingInstance, innerLambdaClass));
        }
      } else {
        // For static methods, instance will be null
        samCall = new JMethodCall(info, instance, referredMethod);
        // if super::method, we need static dispatch
        if (x.lhs instanceof SuperReference) {
          samCall.setStaticDispatchOnly();
        }
      }

      // Add the rest of the parameters from the interface method to methodcall
      // boxing or unboxing and dealing with varargs
      int paramNumber = 0;

      // need to build up an array of passed parameters if we have varargs
      List<JExpression> varArgInitializers = null;
      int varArg = referredMethodBinding.parameters.length - 1;

      // interface Foo { m(int x, int y); } bound to reference foo(int... args)
      // if varargs and incoming param is not already a var-arg, we'll need to convert
      // trailing args of the target interface into an array
      boolean isVarargArgumentSuppliedDirectlyAsAnArray =
          referredMethodBinding.isVarargs()
              && samBinding.parameters.length == referredMethodBinding.parameters.length
              && samBinding.parameters[varArg]
                  .isCompatibleWith(referredMethodBinding.parameters[varArg]);

      if (referredMethodBinding.isVarargs()
          && !isVarargArgumentSuppliedDirectlyAsAnArray) {
        varArgInitializers = Lists.newArrayList();
      }

      while (paramIt.hasNext()) {
        JParameter param = paramIt.next();
        JExpression paramExpr = param.makeRef(info);
        // params may need to be boxed or unboxed
        TypeBinding destParam = null;

        int declarationParameterOffset =
            declarationSamBinding.parameters.length
                - referredMethodBinding.parameters.length;
        // The method declared in the functional interface might have more or less parameters than
        // the method referred by the method reference. In the case of an instance method without
        // an explicit qualifier (A::m vs instance::m) the method in the functional interface will
        // have an additional parameter for the instance preceding all the method parameters.
        // So truncate the value of the index to refer to the right parameter.
        int declarationParameterIndex = Math.max(0,
            Math.min(
                paramNumber
                    + declarationParameterOffset,
                declarationSamBinding.parameters.length - 1)
        );
        TypeBinding samParameterBinding =
            declarationSamBinding.parameters[declarationParameterIndex];
        // if it is not the trailing param or varargs, or interface method is already varargs
        if (varArgInitializers == null
            || !referredMethodBinding.isVarargs()
            || (paramNumber < varArg)) {
          destParam = referredMethodBinding.parameters[paramNumber];
          paramExpr = boxOrUnboxExpression(paramExpr, samParameterBinding, destParam);
          samCall.addArg(paramExpr);
        } else if (!samParameterBinding.isArrayType()) {
          // else add trailing parameters to var-args initializer list for an array
          destParam = referredMethodBinding.parameters[varArg].leafComponentType();
          paramExpr = boxOrUnboxExpression(paramExpr, samParameterBinding, destParam);
          varArgInitializers.add(paramExpr);
        }
        paramNumber++;
      }

      // add trailing new T[] { initializers } var-arg array
      if (varArgInitializers != null) {
        JArrayType lastParamType =
            (JArrayType) typeMap.get(
                referredMethodBinding.parameters[referredMethodBinding.parameters.length - 1]);
        JNewArray newArray =
            JNewArray.createArrayWithInitializers(info, lastParamType, varArgInitializers);
        samCall.addArg(newArray);
      }

      // TODO(rluble): Make this a call to JjsUtils.makeMethodEndStatement once boxing/unboxing
      // is handled there.
      if (samMethod.getType() != JPrimitiveType.VOID) {
        JExpression samExpression = boxOrUnboxExpression(samCall, referredMethodBinding.returnType,
            declarationSamBinding.returnType);
        samMethodBody.getBlock().addStmt(maybeBoxOrUnbox(samExpression, x).makeReturnStatement());
      } else {
        samMethodBody.getBlock().addStmt(samCall.makeStatement());
      }
      samMethod.setBody(samMethodBody);
      innerLambdaClass.addMethod(samMethod);
      ctor.freezeParamTypes();
      samMethod.freezeParamTypes();

      createFunctionalExpressionBridges(innerLambdaClass, x, samMethod);

      JConstructor lambdaCtor = null;
      for (JMethod method : innerLambdaClass.getMethods()) {
        if (method instanceof JConstructor) {
          lambdaCtor = (JConstructor) method;
          break;
        }
      }

      assert lambdaCtor != null;

      // Replace the ReferenceExpression qualifier::method with new lambdaType(qualifier)
      assert lambdaCtor.getEnclosingType() == innerLambdaClass;
      JNewInstance allocLambda = new JNewInstance(info, lambdaCtor);

      if (hasQualifier) {
        JExpression qualifier =  (JExpression) pop();
        // pop qualifier from stack
        allocLambda.addArg(qualifier);
      } else {
        // you can't simultaneously have a qualifier, and have enclosing inner class refs
        // because Java8 won't allow a qualified constructor method reference, e.g. x.Foo::new
        for (JExpression enclosingRef : enclosingThisRefs) {
          allocLambda.addArg(enclosingRef);
        }
      }
      push(allocLambda);
    }

    private JExpression boxOrUnboxExpression(JExpression expr, TypeBinding fromType,
        TypeBinding toType) {
      if (fromType == TypeBinding.VOID || toType == TypeBinding.VOID) {
        return expr;
      }

      if (fromType.isBaseType() && !toType.isBaseType()) {
        return box(expr, JdtUtil.getBaseTypeBinding(curClass.scope, fromType.id));
      }

      if (!fromType.isBaseType() && toType.isBaseType()) {
        return unbox(expr, JdtUtil.getBaseTypeBinding(curClass.scope, toType.id));
      }

      TypeBinding castToType = fromType.genericCast(toType);
      if (castToType == null) {
        return expr;
      }
      return new JCastOperation(expr.getSourceInfo(), typeMap.get(castToType), expr);
    }

    @Override
    public void endVisit(ReturnStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JExpression expression = pop(x.expression);
        push(new JReturnStatement(info, expression));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(SingleNameReference x, BlockScope scope) {
      try {
        JExpression result = resolveNameReference(x, scope);
        if (result == null) {
          push(null);
          return;
        }
        if (x.genericCast != null) {
          JType castType = typeMap.get(x.genericCast);
          result = maybeCast(castType, result);
        }
        push(result);
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(StringLiteral x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        push(getStringLiteral(info, x.constant.stringValue()));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(StringLiteralConcatenation x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        push(getStringLiteral(info, x.constant.stringValue()));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(SuperReference x, BlockScope scope) {
      try {
        assert (typeMap.get(x.resolvedType) == curClass.getClassOrInterface().getSuperClass());
        // Super refs can be modeled as a this ref.
        push(makeThisRef(makeSourceInfo(x)));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(SwitchStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);

        JBlock block = popBlock(info, x.statements);
        JExpression expression = pop(x.expression);

        if (x.expression.resolvedType.isEnum()) {
          // synthesize a call to ordinal().
          expression = synthesizeCallToOrdinal(scope, info, expression);
        }
        push(new JSwitchStatement(info, expression, block));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(SynchronizedStatement x, BlockScope scope) {
      try {
        JBlock block = pop(x.block);
        JExpression expression = pop(x.expression);
        block.addStmt(0, expression.makeStatement());
        push(block);
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(ThisReference x, BlockScope scope) {
      try {
        assert typeMap.get(x.resolvedType) == curClass.getClassOrInterface();
        push(makeThisRef(makeSourceInfo(x)));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(ThrowStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JExpression exception = pop(x.exception);
        push(new JThrowStatement(info, exception));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(TrueLiteral x, BlockScope scope) {
      push(JBooleanLiteral.TRUE);
    }

    @Override
    public void endVisit(TryStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);

        JBlock finallyBlock = pop(x.finallyBlock);
        List<JBlock> catchBlocks = pop(x.catchBlocks);
        JBlock tryBlock = pop(x.tryBlock);

        if (x.resources.length > 0) {
          tryBlock = normalizeTryWithResources(info, x, tryBlock);
        }
        List<JTryStatement.CatchClause> catchClauses = Lists.newArrayList();
        if (x.catchBlocks != null) {
          for (int i = 0; i < x.catchArguments.length; i++) {
            Argument argument = x.catchArguments[i];
            JLocal local = (JLocal) curMethod.locals.get(argument.binding);

            List<JType> catchTypes = Lists.newArrayList();
            if (argument.type instanceof UnionTypeReference) {
              // This is a multiexception
              for (TypeReference type : ((UnionTypeReference) argument.type).typeReferences) {
                catchTypes.add(typeMap.get(type.resolvedType));
              }
            } else {
              // Regular exception
              catchTypes.add(local.getType());
            }
            catchClauses.add(new JTryStatement.CatchClause(catchTypes, local.makeRef(info),
                catchBlocks.get(i)));
          }
        }
        push(new JTryStatement(info, tryBlock, catchClauses, finallyBlock));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    private JBlock normalizeTryWithResources(SourceInfo info, TryStatement x, JBlock tryBlock) {
      /**
       * Apply the following source transformation:
       *
       * try (A1 a1 = new A1(); ... ; An an = new An()) {
       *   ... tryBlock...
       *  } ...catch/finally blocks
       *
       *  to
       *
       * try {
       *   A1 a1 = null; ...; An an = null;
       *   Throwable $exception = null;
       *   try {
       *     a1 = new A1();... ; an = new An();
       *     ... tryBlock...
       *   } catch (Throwable t) {
       *     $exception = t;
       *     throw t;
       *   } finally {
       *    $exception = Exceptions.safeClose(an, $exception);
       *    ...
       *    $exception = Exceptions.safeClose(a1, $exception);
       *  if ($exception != null) {
       *    throw $exception;
       *  }
       * } ...catch/finally blocks
       *
       */

      JBlock outerTryBlock = new JBlock(info);
      // add resource variables
      List<JLocal> resourceVariables = Lists.newArrayList();
      for (int i = x.resources.length - 1; i >= 0; i--) {
        // Needs to iterate back to front to be inline with the contents of the stack.

        JDeclarationStatement resourceDecl = pop(x.resources[i]);

        JLocal resourceVar = (JLocal) curMethod.locals.get(x.resources[i].binding);
        resourceVariables.add(0, resourceVar);
        tryBlock.addStmt(0, resourceDecl);
      }

      // add exception variable
      JLocal exceptionVar = createLocalThrowable(info, "$primary_ex");

      outerTryBlock.addStmt(makeDeclaration(info, exceptionVar, JNullLiteral.INSTANCE));

      // create catch block
      List<JTryStatement.CatchClause> catchClauses = Lists.newArrayListWithCapacity(1);

      List<JType> clauseTypes = Lists.newArrayListWithCapacity(1);
      clauseTypes.add(javaLangThrowable);

      //     add catch exception variable.
      JLocal catchVar = createLocalThrowable(info, "$caught_ex");

      JBlock catchBlock = new JBlock(info);
      catchBlock.addStmt(createAssignment(info, javaLangThrowable, exceptionVar, catchVar));
      catchBlock.addStmt(new JThrowStatement(info, exceptionVar.makeRef(info)));

      catchClauses.add(new JTryStatement.CatchClause(clauseTypes, catchVar.makeRef(info),
          catchBlock));

      // create finally block
      JBlock finallyBlock = new JBlock(info);
      for (int i = x.resources.length - 1; i >= 0; i--) {
        finallyBlock.addStmt(createCloseBlockFor(info,
            resourceVariables.get(i), exceptionVar));
      }

      // if (exception != null) throw exception
      JExpression exceptionNotNull = new JBinaryOperation(info, JPrimitiveType.BOOLEAN,
          JBinaryOperator.NEQ, exceptionVar.makeRef(info), JNullLiteral.INSTANCE);
      finallyBlock.addStmt(new JIfStatement(info, exceptionNotNull,
          new JThrowStatement(info, exceptionVar.makeRef(info)), null));

      // Stitch all together into a inner try block
      outerTryBlock.addStmt(new JTryStatement(info, tryBlock, catchClauses,
            finallyBlock));
      return outerTryBlock;
    }

    private JLocal createLocalThrowable(SourceInfo info, String prefix) {
      int index = curMethod.body.getLocals().size() + 1;
      return JProgram.createLocal(info, prefix + "_" + index,
          javaLangThrowable, false, curMethod.body);
    }

    private JStatement createCloseBlockFor(
        SourceInfo info, JLocal resourceVar, JLocal exceptionVar) {
      /**
       * Create the following code:
       *
       * $ex = Exceptions.safeClose(resource, $ex);
       *
       * which is equivalent to
       *
       * if (resource != null) {
       *   try {
       *     resource.close();
       *   } catch (Throwable t) {
       *     if ($ex == null) {
       *       $ex = t;
       *     } else {
       *      $ex.addSuppressed(t);
       *     }
       *   }
       */

      JMethodCall safeCloseCall = new JMethodCall(info, null, SAFE_CLOSE_METHOD);
      safeCloseCall.addArg(0, resourceVar.makeRef(info));
      safeCloseCall.addArg(1, exceptionVar.makeRef(info));

      return new JBinaryOperation(info, javaLangThrowable, JBinaryOperator.ASG,
          exceptionVar.makeRef(info), safeCloseCall).makeStatement();
    }

    private JStatement createAssignment(SourceInfo info, JType type, JLocal lhs, JLocal rhs) {
      return new JBinaryOperation(info, type, JBinaryOperator.ASG, lhs.makeRef(info),
          rhs.makeRef(info)).makeStatement();
    }

    @Override
    public void endVisit(TypeDeclaration x, ClassScope scope) {
      endVisit(x);
    }

    @Override
    public void endVisit(TypeDeclaration x, CompilationUnitScope scope) {
      endVisit(x);
    }

    @Override
    public void endVisit(UnaryExpression x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JUnaryOperator op;
        int operator = ((x.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT);

        switch (operator) {
          case OperatorIds.MINUS:
            op = JUnaryOperator.NEG;
            break;

          case OperatorIds.NOT:
            op = JUnaryOperator.NOT;
            break;

          case OperatorIds.PLUS:
            // Odd case.. useless + operator; just leave the operand on the
            // stack.
            return;

          case OperatorIds.TWIDDLE:
            op = JUnaryOperator.BIT_NOT;
            break;

          default:
            throw new InternalCompilerException("Unexpected operator for unary expression");
        }

        JExpression expression = pop(x.expression);
        push(new JPrefixOperation(info, op, expression));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisit(WhileStatement x, BlockScope scope) {
      try {
        SourceInfo info = makeSourceInfo(x);
        JStatement action = pop(x.action);
        JExpression condition = pop(x.condition);
        push(new JWhileStatement(info, condition, action));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public void endVisitValid(TypeDeclaration x, BlockScope scope) {
      endVisit(x);
      if (!x.binding.isAnonymousType()) {
        // Class declaration as a statement; insert a dummy statement.
        push(null);
      }
    }

    @Override
    public boolean visit(AnnotationMethodDeclaration x, ClassScope classScope) {
      return visit((MethodDeclaration) x, classScope);
    }

    @Override
    public boolean visit(Argument x, BlockScope scope) {
      // handled by parents
      return true;
    }

    @Override
    public boolean visit(Block x, BlockScope scope) {
      x.statements = reduceToReachable(x.statements);
      return true;
    }

    @Override
    public boolean visit(ConstructorDeclaration x, ClassScope scope) {
      try {
        JConstructor method = (JConstructor) typeMap.get(x.binding);
        assert !method.isExternal();
        JMethodBody body = new JMethodBody(method.getSourceInfo());
        method.setBody(body);
        pushMethodInfo(new MethodInfo(method, body, x.scope));

        // Map all arguments.
        Iterator<JParameter> it = method.getParams().iterator();

        // Enum arguments have no mapping.
        if (curClass.classType.isEnumOrSubclass() != null) {
          // Skip past name and ordinal.
          it.next();
          it.next();
        }

        // Map synthetic arguments for outer this.
        ReferenceBinding declaringClass = (ReferenceBinding) x.binding.declaringClass.erasure();
        boolean isNested = JdtUtil.isInnerClass(declaringClass);
        if (isNested) {
          NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
          if (nestedBinding.enclosingInstances != null) {
            for (SyntheticArgumentBinding argument : nestedBinding.enclosingInstances) {
              curMethod.locals.put(argument, it.next());
            }
          }
        }

        // Map user arguments.
        if (x.arguments != null) {
          for (Argument argument : x.arguments) {
            curMethod.locals.put(argument.binding, it.next());
          }
        }

        // Map synthetic arguments for locals.
        if (isNested) {
          // add synthetic args for locals
          NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
          // add synthetic args for outer this and locals
          if (nestedBinding.outerLocalVariables != null) {
            for (SyntheticArgumentBinding argument : nestedBinding.outerLocalVariables) {
              curMethod.locals.put(argument, it.next());
            }
          }
        }

        x.statements = reduceToReachable(x.statements);
        return true;
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public boolean visit(ExplicitConstructorCall explicitConstructor, BlockScope scope) {
      scope.methodScope().isConstructorCall = true;
      return true;
    }

    @Override
    public boolean visit(FieldDeclaration x, MethodScope scope) {
      try {
        assert !typeMap.get(x.binding).isExternal();
        pushInitializerMethodInfo(x, scope);
        return true;
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public boolean visit(Initializer x, MethodScope scope) {
      try {
        pushInitializerMethodInfo(x, scope);
        return true;
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public boolean visit(LocalDeclaration x, BlockScope scope) {
      try {
        createLocal(x);
        return true;
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public boolean visit(MarkerAnnotation annotation, BlockScope scope) {
      return false;
    }

    @Override
    public boolean visit(MethodDeclaration x, ClassScope scope) {
      try {
        JMethod method = typeMap.get(x.binding);
        assert !method.isExternal();
        JMethodBody body = null;
        if (!method.isJsniMethod()) {
          body = new JMethodBody(method.getSourceInfo());
          method.setBody(body);
        }
        pushMethodInfo(new MethodInfo(method, body, x.scope));

        // Map user arguments.
        Iterator<JParameter> it = method.getParams().iterator();
        if (x.arguments != null) {
          for (Argument argument : x.arguments) {
            curMethod.locals.put(argument.binding, it.next());
          }
        }
        x.statements = reduceToReachable(x.statements);
        return true;
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    @Override
    public boolean visit(NormalAnnotation annotation, BlockScope scope) {
      return false;
    }

    @Override
    public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
      return false;
    }

    @Override
    public boolean visit(SwitchStatement x, BlockScope scope) {
      x.statements = reduceToReachable(x.statements);
      return true;
    }

    @Override
    public boolean visit(TryStatement x, BlockScope scope) {
      try {
        if (x.catchBlocks != null) {
          for (Argument argument : x.catchArguments) {
            createLocal(argument);
          }
        }
        return true;
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

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

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

    @Override
    public boolean visitValid(TypeDeclaration x, BlockScope scope) {
      // Local types actually need to be created now.
      createTypes(x);
      resolveTypeRefs(x);
      createMembers(x);
      return visit(x);
    }

    protected void endVisit(TypeDeclaration x) {
      JDeclaredType type = curClass.type;

      // Synthesize super clinit calls.
      if (type instanceof JClassType) {
        Iterable<JInterfaceType> interfacesToInitialize =
            Iterables.transform(
                JdtUtil.getSuperInterfacesRequiringInitialization(x.binding),
                new Function<ReferenceBinding, JInterfaceType>() {
                  @Override
                  public JInterfaceType apply(ReferenceBinding referenceBinding) {
                    return (JInterfaceType) typeMap.get(referenceBinding);
                  }
                });
        JjsUtils.synthesizeStaticInitializerChain(type, interfacesToInitialize);
      }

      // Implement getClass() implementation for all non-Object classes.
      if (isSyntheticGetClassNeeded(x, type) && !type.isAbstract()) {
        implementGetClass(type);
      }

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

      if (type instanceof JClassType && type.isJsNative()) {
        maybeImplementJavaLangObjectMethodsOnNativeClass(type);
      }
      addBridgeMethods(x.binding);

      curClass = classStack.pop();
    }

    protected JBlock pop(Block x) {
      return (x == null) ? null : (JBlock) pop();
    }

    protected JExpression pop(Expression x) {
      if (x == null) {
        return null;
      }
      JExpression result = (JExpression) pop();
      if (result == null) {
        assert x instanceof NameReference;
        return null;
      }
      result = maybeBoxOrUnbox(result, x);
      return result;
    }

    protected <T extends JExpression> List<T> performBoxUnboxConversions(
        List<T> result, Expression[] expressions) {
      for (int i = 0; i < result.size(); i++) {
        result.set(i, (T) maybeBoxOrUnbox(result.get(i), expressions[i]));
      }
      return result;
    }

    @SuppressWarnings("unchecked")
    protected List<JExpression> pop(Expression[] expressions) {
      if (expressions == null) {
        return Collections.emptyList();
      }

      return  (List<JExpression>) popList(Collections2.filter(Arrays.asList(expressions),
          Predicates.notNull()).size());
    }

    protected JDeclarationStatement pop(LocalDeclaration decl) {
      return (decl == null) ? null : (JDeclarationStatement) pop();
    }

    protected JStatement pop(Statement x) {
      JNode pop = (x == null) ? null : pop();
      if (x instanceof Expression) {
        return maybeBoxOrUnbox((JExpression) pop, (Expression) x).makeStatement();
      }
      return (JStatement) pop;
    }

    @SuppressWarnings("unchecked")
    protected <T extends JStatement> List<T> pop(Statement[] statements) {
      if (statements == null) {
        return Collections.emptyList();
      }
      List<T> result = (List<T>) popList(statements.length);
      int i = 0;
      for (ListIterator<T> it = result.listIterator(); it.hasNext(); ++i) {
        Object element = it.next();
        if (element == null) {
          it.remove();
        } else if (element instanceof JExpression) {
          it.set((T)
              maybeBoxOrUnbox((JExpression) element, (Expression) statements[i]).makeStatement());
        }
      }
      return result;
    }

    protected JBlock popBlock(SourceInfo info, Statement statement) {
      JStatement stmt = pop(statement);
      if (stmt instanceof JBlock) {
        return (JBlock) stmt;
      }
      JBlock block = new JBlock(info);
      if (stmt != null) {
        block.addStmt(stmt);
      }
      return block;
    }

    protected JBlock popBlock(SourceInfo info, Statement[] statements) {
      List<JStatement> stmts = pop(statements);
      JBlock block = new JBlock(info);
      block.addStmts(stmts);
      return block;
    }

    protected void pushBinaryOp(Assignment x, JBinaryOperator op) {
      pushBinaryOp(x, op, x.lhs, x.expression);
    }

    protected void pushBinaryOp(BinaryExpression x, JBinaryOperator op) {
      pushBinaryOp(x, op, x.left, x.right);
    }

    protected boolean visit(TypeDeclaration x) {
      JDeclaredType type = (JDeclaredType) typeMap.get(x.binding);
      assert !type.isExternal();
      classStack.push(curClass);
      curClass = new ClassInfo(type, x);

      /*
       * It's okay to defer creation of synthetic fields, they can't be
       * referenced until we analyze the code.
       */
      SourceTypeBinding binding = x.binding;
      if (JdtUtil.isInnerClass(binding)) {
        // add synthetic fields for outer this and locals
        assert (type instanceof JClassType);
        NestedTypeBinding nestedBinding = (NestedTypeBinding) binding;
        if (nestedBinding.enclosingInstances != null) {
          for (SyntheticArgumentBinding argument : nestedBinding.enclosingInstances) {
            createSyntheticField(argument, type, Disposition.THIS_REF);
          }
        }

        if (nestedBinding.outerLocalVariables != null) {
          for (SyntheticArgumentBinding argument : nestedBinding.outerLocalVariables) {
            // See InnerClassTest.testOuterThisFromSuperCall().
            boolean isReallyThisRef = false;
            if (argument.actualOuterLocalVariable instanceof SyntheticArgumentBinding) {
              SyntheticArgumentBinding outer =
                  (SyntheticArgumentBinding) argument.actualOuterLocalVariable;
              if (outer.matchingField != null) {
                JField field = typeMap.get(outer.matchingField);
                if (field.isThisRef()) {
                  isReallyThisRef = true;
                }
              }
            }
            createSyntheticField(argument, type, isReallyThisRef ? Disposition.THIS_REF
                : Disposition.FINAL);
          }
        }
      }
      return true;
    }

    /**
     * <p>
     * Add a bridge method to <code>clazzBinding</code> for any method it
     * inherits that implements an interface method but that has a different
     * erased signature from the interface method.
     * </p>
     *
     * <p>
     * The need for these bridges was pointed out in issue 3064. The goal is
     * that virtual method calls through an interface type are translated to
     * JavaScript that will function correctly. If the interface signature
     * matches the signature of the implementing method, then nothing special
     * needs to be done. If they are different, due to the use of generics, then
     * GenerateJavaScriptAST is careful to do the right thing. There is a
     * remaining case, though, that GenerateJavaScriptAST is not in a good
     * position to fix: a method could be inherited from a superclass, used to
     * implement an interface method that has a different type signature, and
     * does not have the interface method in its list of overrides. In that
     * case, a bridge method should be added that overrides the interface method
     * and then calls the implementation method.
     * </p>
     *
     * <p>
     * This method should only be called once all regular, non-bridge methods
     * have been installed on the GWT types.
     * </p>
     */
    private void addBridgeMethods(SourceTypeBinding classBinding) {
      /*
       * JDT adds bridge methods in all the places GWT needs them. Use JDT's
       * bridge methods.
       */
      if (classBinding.syntheticMethods() != null) {
        for (SyntheticMethodBinding syntheticMethodBinding : classBinding.syntheticMethods()) {
          if (syntheticMethodBinding.purpose == SyntheticMethodBinding.BridgeMethod
              && !syntheticMethodBinding.isStatic()) {
            createBridgeMethod(syntheticMethodBinding);
          }
        }
      }
    }

    private JBinaryOperation assignSyntheticField(SourceInfo info, SyntheticArgumentBinding arg) {
      JParameter param = (JParameter) curMethod.locals.get(arg);
      assert param != null;
      JField field = curClass.syntheticFields.get(arg);
      assert field != null;
      JFieldRef lhs = makeInstanceFieldRef(info, field);
      return
          new JBinaryOperation(info, lhs.getType(), JBinaryOperator.ASG, lhs, param.makeRef(info));
    }

    private JExpression box(JExpression original, BaseTypeBinding primitiveType) {
      return box(original, primitiveType, false);
    }

    private JExpression box(
        JExpression original, BaseTypeBinding primitiveType, boolean doNotAutobox) {
      // Add a cast to the correct primitive type if needed.
      JType targetPrimitiveType = typeMap.get(primitiveType);
      if (original.getType() != targetPrimitiveType) {
        original = new JCastOperation(original.getSourceInfo(), targetPrimitiveType, original);
      }

      if (doNotAutobox) {
        // Protect the primitive @DoNotAutobox values from optimizations, etc but encapsulating
        // them in an opaque unsafe coercion to Object.
        return new JUnsafeTypeCoercion(original.getSourceInfo(), javaLangObject, original);
      }

      ClassScope scope = curClass.scope;
      JMethod boxingMethod = typeMap.get(JdtUtil.getBoxingMethodBinding(scope, primitiveType));
      return new JMethodCall(original.getSourceInfo(), null, boxingMethod, original);
    }

    private JExpression unbox(JExpression original, BaseTypeBinding primitiveType) {
      return unbox(original, primitiveType, true);
    }

    private JExpression unbox(
        JExpression original, BaseTypeBinding primitiveType, boolean needsExplicitCast) {

      ClassScope scope = curClass.scope;
      if (needsExplicitCast) {
        // Direct cast from non-boxed-type reference type to a primitive type,
        // wrap with a cast operation of the (boxed) expected type.
        JReferenceType boxedType =
            (JReferenceType) typeMap.get(JdtUtil.getBoxedTypeBinding(scope, primitiveType));
        original =
            new JCastOperation(original.getSourceInfo(), boxedType, original);
      }
      JMethod unboxingMethod = typeMap.get(JdtUtil.getUnboxingMethodBinding(scope, primitiveType));
      return new JMethodCall(original.getSourceInfo(), original, unboxingMethod);
    }

    private void createBridgeMethod(SyntheticMethodBinding jdtBridgeMethod) {
      JMethod targetMethod = typeMap.get(jdtBridgeMethod.targetMethod);
      createBridgeMethod(curClass.type, jdtBridgeMethod, targetMethod);
    }

    /**
     * Create a bridge method. It calls a same-named method with the same
     * arguments, but with a different type signature.
     */
    private JMethod createBridgeMethod(
        JDeclaredType enclosingType, MethodBinding sourceMethodBinding, JMethod targetMethod) {

      JType returnType = typeMap.get(sourceMethodBinding.returnType);
      Iterable<JType> parameterTypes = mapTypes(sourceMethodBinding.parameters);
      Iterable<JClassType> thrownExceptionTypes = mapTypes(sourceMethodBinding.thrownExceptions);

      SourceInfo info = targetMethod.getSourceInfo();
      JMethod bridgeMethod =
          new JMethod(info, targetMethod.getName(), enclosingType, returnType, false, false,
              targetMethod.isFinal(), targetMethod.getAccess());
      bridgeMethod.setBody(new JMethodBody(info));
      if (enclosingType instanceof JInterfaceType) {
        // Mark bridges created in interfaces as default methods so they are processed correctly
        // by the rest of the pipeline.
        bridgeMethod.setDefaultMethod(true);
      }
      bridgeMethod.setSynthetic();

      enclosingType.addMethod(bridgeMethod);
      int paramIndex = 0;
      List<JParameter> implParams = targetMethod.getParams();
      for (JType parameterType : parameterTypes) {
        JParameter parameter = implParams.get(paramIndex++);
        bridgeMethod.createFinalParameter(
            parameter.getSourceInfo(), parameter.getName(), parameterType);
      }
      for (JClassType thrownException : thrownExceptionTypes) {
        bridgeMethod.addThrownException(thrownException);
      }
      bridgeMethod.freezeParamTypes();

      // create a call and pass all arguments through, casting if necessary
      JMethodCall call = new JMethodCall(info, makeThisRef(info), targetMethod);
      for (int i = 0; i < bridgeMethod.getParams().size(); i++) {
        JParameter param = bridgeMethod.getParams().get(i);
        call.addArg(maybeCast(implParams.get(i).getType(), param.makeRef(info)));
      }

      JMethodBody body = (JMethodBody) bridgeMethod.getBody();
      if (bridgeMethod.getType() == JPrimitiveType.VOID) {
        body.getBlock().addStmt(call.makeStatement());
      } else {
        body.getBlock().addStmt(call.makeReturnStatement());
      }
      typeMap.setMethod(sourceMethodBinding, bridgeMethod);
      return bridgeMethod;
    }

    private void writeEnumValuesMethod(JEnumType type, JMethod method) {
      // return new E[]{A,B,C};
      JArrayType enumArrayType = new JArrayType(type);
      SourceInfo info = type.getSourceInfo();
      List<JExpression> initializers = Lists.newArrayList();
      for (JEnumField field : type.getEnumList()) {
        JFieldRef fieldRef = new JFieldRef(info, null, field, type);
        initializers.add(fieldRef);
      }
      JNewArray valuesArrayCopy =
          JNewArray.createArrayWithInitializers(info, enumArrayType, initializers);
      if (type.getEnumList().size() > MAX_INLINEABLE_ENUM_SIZE) {
        // Only inline values() if it is small.
        method.setInliningMode(InliningMode.DO_NOT_INLINE);
      }
      JjsUtils.replaceMethodBody(method, valuesArrayCopy);
    }

    private JLocal createLocal(LocalDeclaration x) {
      LocalVariableBinding b = x.binding;
      TypeBinding resolvedType = x.type.resolvedType;
      JType localType;
      if (resolvedType.constantPoolName() != null) {
        localType = typeMap.get(resolvedType);
      } else {
        // Special case, a statically unreachable local type.
        localType = JReferenceType.NULL_TYPE;
      }
      SourceInfo info = makeSourceInfo(x);
      JLocal newLocal =
          JProgram.createLocal(info, intern(x.name), localType, b.isFinal(), curMethod.body);
      curMethod.locals.put(b, newLocal);
      return newLocal;
    }

    private JField createSyntheticField(SyntheticArgumentBinding arg, JDeclaredType enclosingType,
        Disposition disposition) {
      JType type = typeMap.get(arg.type);
      SourceInfo info = enclosingType.getSourceInfo();
      // Construct field name including position because JDT can sometimes create multiple synthetic
      // fields with the same name. The increased name size won't affect optimized output since
      // references are pruned and renamed.
      String fieldName = intern(intern(arg.name) + arg.resolvedPosition);
      JField field = new JField(info, fieldName, enclosingType, type, false, disposition,
          AccessModifier.PRIVATE);
      enclosingType.addField(field);
      curClass.syntheticFields.put(arg, field);
      if (arg.matchingField != null) {
        typeMap.setField(arg.matchingField, field);
      }
      return field;
    }

    private JExpression getConstant(SourceInfo info, Constant constant) {
      switch (constant.typeID()) {
        case TypeIds.T_int:
          return JIntLiteral.get(constant.intValue());
        case TypeIds.T_byte:
          return JIntLiteral.get(constant.byteValue());
        case TypeIds.T_short:
          return JIntLiteral.get(constant.shortValue());
        case TypeIds.T_char:
          return JCharLiteral.get(constant.charValue());
        case TypeIds.T_float:
          return JFloatLiteral.get(constant.floatValue());
        case TypeIds.T_double:
          return JDoubleLiteral.get(constant.doubleValue());
        case Constant.T_boolean:
          return JBooleanLiteral.get(constant.booleanValue());
        case Constant.T_long:
          return JLongLiteral.get(constant.longValue());
        case Constant.T_JavaLangString:
          return getStringLiteral(info, constant.stringValue());
        case Constant.T_null:
          return JNullLiteral.INSTANCE;
        default:
          throw new InternalCompilerException("Unknown Constant type: " + constant.typeID());
      }
    }

    /**
     * Get a new label of a particular name, or create a new one if it doesn't
     * exist already.
     */
    private JLabel getOrCreateLabel(SourceInfo info, char[] name) {
      if (name == null) {
        return null;
      }
      String sname = intern(name);
      JLabel jlabel = curMethod.labels.get(sname);
      if (jlabel == null) {
        jlabel = new JLabel(info, sname);
        curMethod.labels.put(sname, jlabel);
      }
      return jlabel;
    }

    private JStringLiteral getStringLiteral(SourceInfo info, char[] chars) {
      return new JStringLiteral(info, intern(chars), javaLangString);
    }

    private JStringLiteral getStringLiteral(SourceInfo info, String string) {
      return new JStringLiteral(info, intern(string), javaLangString);
    }

    private void implementGetClass(JDeclaredType type) {
      // TODO(rluble): Object.getClass() should be final our JRE, when that is done, GwtAstBuilder
      // creates overrides for convenience and should unmark Object.getClass as final for
      // consistency.
      JMethod method = type.getMethods().get(GET_CLASS_METHOD_INDEX);
      assert (GET_CLASS_METHOD_NAME.equals(method.getName()));
      SourceInfo info = method.getSourceInfo();
      if (type.isJsoType()) {
        // Native types and JSOs get a synthetic get class that return JavaScriptObject.class.
        //
        // return Cast.getClass(this)
        JjsUtils.replaceMethodBody(method,
            new JMethodCall(info, null, CAST_GET_CLASS_METHOD, new JThisRef(info, type)));
      } else {
        JjsUtils.replaceMethodBody(method, new JClassLiteral(info, type));
      }
    }

    private void maybeImplementJavaLangObjectMethodsOnNativeClass(JDeclaredType type) {
      maybeCreateSyntheticJavaLangObjectMethodNativeOverride(
          type, EQUALS_METHOD_NAME, JPrimitiveType.BOOLEAN, javaLangObject);
      maybeCreateSyntheticJavaLangObjectMethodNativeOverride(
          type, HASHCODE_METHOD_NAME, JPrimitiveType.INT);
      maybeCreateSyntheticJavaLangObjectMethodNativeOverride(
          type, TO_STRING_METHOD_NAME, javaLangString);
    }

    private void maybeCreateSyntheticJavaLangObjectMethodNativeOverride(
        JDeclaredType type, String name, JType returnType, JType... parameterTypes) {
      SourceInfo info = type.getSourceInfo();
      JMethod method =
          new JMethod(info, name, type, returnType, false, false, false, AccessModifier.PUBLIC);
      int i = 0;
      for (JType parameterType : parameterTypes) {
        method.createParameter(info, "arg" + i++, parameterType);
      }
      method.freezeParamTypes();
      // Do not mark this methods as synthetic because of the risk of missing some checks in
      // JsInteropRestrictionChecker where we skip synthetic methods in many of the checks.
      assert (!method.isSynthetic());
      // Creating a method without a body makes it native.
      assert (method.isJsNative());
      final String signature = method.getJsniSignature(false, false);
      boolean alreadyExists = Iterables.any(type.getMethods(), new Predicate<JMethod>() {
        @Override
        public boolean apply(JMethod typeMethod) {
          return typeMethod.getJsniSignature(false, false).equals(signature);
        }
      });
      if (alreadyExists) {
        return;
      }
      type.addMethod(method);
      // This method is declared in a native JsType, make sure JsInfo is populated correctly, by
      // applying the JsType rules.
      JsInteropUtil.maybeSetJsInteropProperties(method, shouldExport(method));
      assert (method.getJsMemberType() == JsMemberType.METHOD);
    }

    private JDeclarationStatement makeDeclaration(SourceInfo info, JLocal local,
        JExpression value) {
      return new JDeclarationStatement(info, local.makeRef(info), value);
    }

    private JFieldRef makeInstanceFieldRef(SourceInfo info, JField field) {
      return new JFieldRef(info, makeThisRef(info), field, curClass.classType);
    }

    private JExpression makeLocalRef(SourceInfo info, LocalVariableBinding b, MethodInfo method) {
      return method.locals.get(b).makeRef(info);
    }

    private JThisRef makeThisRef(SourceInfo info) {
      return new JThisRef(info, curClass.getClassOrInterface());
    }

    private JExpression resolveThisReference(SourceInfo info, ReferenceBinding targetType,
        boolean exactMatch, BlockScope scope) {
      targetType = (ReferenceBinding) targetType.erasure();

      Object[] path = scope.getEmulationPath(targetType, exactMatch, false);
      if (path == null) {
        throw new InternalCompilerException("No emulation path.");
      }
      if (path == BlockScope.EmulationPathToImplicitThis) {
        return makeThisRef(info);
      }
      JExpression ref;
      ReferenceBinding type;
      if (curMethod.scope.isInsideInitializer() && path[0] instanceof SyntheticArgumentBinding) {
        SyntheticArgumentBinding b = (SyntheticArgumentBinding) path[0];
        JField field = curClass.syntheticFields.get(b);
        assert field != null;
        ref = makeInstanceFieldRef(info, field);
        type = (ReferenceBinding) b.type.erasure();
      } else if (path[0] instanceof SyntheticArgumentBinding) {
        SyntheticArgumentBinding b = (SyntheticArgumentBinding) path[0];
        JParameter param = (JParameter) curMethod.locals.get(b);
        assert param != null;
        ref = param.makeRef(info);
        type = (ReferenceBinding) b.type.erasure();
      } else if (path[0] instanceof FieldBinding) {
        FieldBinding b = (FieldBinding) path[0];
        JField field = typeMap.get(b);
        assert field != null;
        ref = makeInstanceFieldRef(info, field);
        type = (ReferenceBinding) b.type.erasure();
      } else {
        throw new InternalCompilerException("Unknown emulation path.");
      }
      for (int i = 1; i < path.length; ++i) {
        SyntheticMethodBinding b = (SyntheticMethodBinding) path[i];
        assert type == b.declaringClass.erasure();
        FieldBinding fieldBinding = b.targetReadField;
        JField field = typeMap.get(fieldBinding);
        assert field != null;
        ref = new JFieldRef(info, ref, field, curClass.classType);
        type = (ReferenceBinding) fieldBinding.type.erasure();
      }
      return ref;
    }

    private JExpression maybeBoxOrUnbox(JExpression original, int implicitConversion) {
      return maybeBoxOrUnbox(original, implicitConversion, false);
    }

    private JExpression maybeBoxOrUnbox(
        JExpression original, int implicitConversion, boolean doNotAutobox) {
      if (JdtUtil.requiresBoxing(implicitConversion)) {
        return box(original, JdtUtil.getBoxingPrimitiveType(curClass.scope, implicitConversion),
            doNotAutobox);
      }
      if (JdtUtil.requiresUnboxing(implicitConversion)) {
        return unbox(original, JdtUtil.getUnboxingPrimitiveType(curClass.scope, implicitConversion),
            JdtUtil.needsCastBeforeUnbox(curClass.scope, implicitConversion));
      }
      return original;
    }

    private JExpression maybeCast(JType[] expected, JExpression expression) {
      for (JType type : expected) {
        expression = maybeCast(type, expression);
      }
      return expression;
    }

    private JExpression maybeCast(JType expected, JExpression expression) {
      if (expected != expression.getType()) {
        // Must be a generic cast; insert a cast operation.
        return new JCastOperation(expression.getSourceInfo(), expected, expression);
      }
      return expression;
    }

      private JExpression maybeInsertUnsafeTypeCoercion(JType expected, JExpression expression) {
      if (expected != expression.getType()) {
        // A generic call marked as @UncheckedCast.
        return new JUnsafeTypeCoercion(expression.getSourceInfo(), expected, expression);
      }

      return expression;
    }

    private JNode pop() {
      return nodeStack.remove(nodeStack.size() - 1);
    }

    private List<JExpression> popCallArguments(SourceInfo info, Expression[] arguments,
        MethodBinding methodBinding) {
      List<JExpression> args = pop(arguments);
      for (int i = 0; i < args.size(); i++) {
        // Account for varargs parameter.
        int parameterIndex = Math.min(i, methodBinding.parameters.length - 1);
        args.set(i, maybeBoxOrUnbox(
            args.get(i),
            arguments[i].implicitConversion,
            isDoNotAutoBoxParameter(methodBinding, parameterIndex)));
      }
      if (!methodBinding.isVarargs()) {
        return args;
      }

      // Handle the odd var-arg case.
      if (arguments == null) {
        // Get writable collection (args is currently Collections.emptyList()).
        args = Lists.newArrayListWithCapacity(1);
      }

      TypeBinding[] params = methodBinding.parameters;
      int varArg = params.length - 1;

      // See if there's a single varArg which is already an array.
      if (args.size() == params.length) {
        if (arguments[varArg].resolvedType.isCompatibleWith(params[varArg])) {
          // Already the correct array type.
          return args;
        }
      }

      // Need to synthesize an appropriately-typed array.
      List<JExpression> tail = args.subList(varArg, args.size());
      List<JExpression> initializers = Lists.newArrayList(tail);
      tail.clear();
      JArrayType lastParamType = (JArrayType) typeMap.get(params[varArg]);
      JNewArray newArray = JNewArray.createArrayWithInitializers(info, lastParamType, initializers);
      args.add(newArray);
      return args;
    }

    private boolean isDoNotAutoBoxParameter(MethodBinding methodBinding, int parameterIndex) {
      AnnotationBinding[][] parameterAnnotations =
          methodBinding.original().getParameterAnnotations();
      return parameterAnnotations != null
          && parameterAnnotations.length > parameterIndex
          && parameterAnnotations[parameterIndex] != null
          && JdtUtil.getAnnotationByName(parameterAnnotations[parameterIndex],
          "javaemul.internal.annotations.DoNotAutobox") != null;
    }

    private List<? extends JNode> popList(int count) {
      List<JNode> tail = nodeStack.subList(nodeStack.size() - count, nodeStack.size());
      // Make a copy.
      List<JNode> result = Lists.newArrayList(tail);
      // Causes the tail to be removed.
      tail.clear();
      return result;
    }

    private void popMethodInfo() {
      curMethod = methodStack.pop();
    }

    private void processEnumType(JEnumType type) {
      // $clinit, $init, getClass, valueOf, values
      JMethod valueOfMethod =
          type.getMethods().get(getEnumMethodsStartIndex(type) + VALUE_OF_METHOD_OFFSET);
      JMethod valuesMethod =
      type.getMethods().get(getEnumMethodsStartIndex(type) + VALUES_METHOD_OFFSET);
      {
        assert VALUE_OF_METHOD_NAME.equals(valueOfMethod.getName());
        writeEnumValueOfMethod(type, valueOfMethod, valuesMethod);
      }
      {
        assert VALUES_METHOD_NAME.equals(valuesMethod.getName());
        writeEnumValuesMethod(type, valuesMethod);
      }
    }

    private void processNativeMethod(MethodDeclaration x) {
      JMethod method = curMethod.method;
      JsniMethod jsniMethod = jsniMethods.get(x);
      if (jsniMethod == null) {
        method.setBody(null);
        return;
      }
      SourceInfo info = method.getSourceInfo();
      JsFunction jsFunction = jsniMethod.function();
      JsniMethodBody body = new JsniMethodBody(info);
      method.setBody(body);
      jsFunction.setFromJava(true);
      body.setFunc(jsFunction);
      // Resolve locals, params, and JSNI.
      JsParameterResolver localResolver = new JsParameterResolver(jsFunction);
      localResolver.accept(jsFunction);
      JsniReferenceCollector jsniReferenceCollector = new JsniReferenceCollector(body);
      jsniReferenceCollector.accept(jsFunction);
    }

    private void processSuperCallLocalArgs(ReferenceBinding superClass, JMethodCall call) {
      if (superClass.syntheticOuterLocalVariables() != null) {
        for (SyntheticArgumentBinding arg : superClass.syntheticOuterLocalVariables()) {
          // TODO: use emulation path here.
          // Got to be one of my params
          JType varType = typeMap.get(arg.type);
          String varName = intern(arg.name);
          JParameter param = null;
          for (JParameter paramIt : curMethod.method.getParams()) {
            if (varType == paramIt.getType() && varName.equals(paramIt.getName())) {
              param = paramIt;
            }
          }
          if (param == null) {
            throw new InternalCompilerException(
                "Could not find matching local arg for explicit super ctor call.");
          }
          call.addArg(param.makeRef(call.getSourceInfo()));
        }
      }
    }

    // Only called on nested instances constructors (explicitConstructorCalls) that are of the
    // form: outer.super(...) or super(...)
    //
    // Will set outer (in the first case) or the implicit enclosing object reference to
    // be the first parameter of super(...)
    private void processSuperCallThisArgs(ReferenceBinding superClass, JMethodCall call,
        JExpression qualifier, Expression qualification) {
      // Explicit super calls can only happend inside constructors
      assert curMethod.scope.isInsideConstructor();
      if (superClass.syntheticEnclosingInstanceTypes() != null) {
        // there can only be ONE immediate enclosing instance.
        assert superClass.syntheticEnclosingInstanceTypes().length == 1;
        ReferenceBinding targetType = superClass.syntheticEnclosingInstanceTypes()[0];
        if (qualification != null) {
          // Outer object is the qualifier.
          call.addArg(qualifier);
        } else {
          // Get implicit outer object.
          call.addArg(
              resolveThisReference(call.getSourceInfo(), targetType, false, curMethod.scope));
        }
      }
    }

    private void processThisCallLocalArgs(ReferenceBinding binding, JMethodCall call) {
      if (binding.syntheticOuterLocalVariables() != null) {
        for (SyntheticArgumentBinding arg : binding.syntheticOuterLocalVariables()) {
          JParameter param = (JParameter) curMethod.locals.get(arg);
          assert param != null;
          call.addArg(param.makeRef(call.getSourceInfo()));
        }
      }
    }

    private void processThisCallThisArgs(ReferenceBinding binding, JMethodCall call) {
      if (binding.syntheticEnclosingInstanceTypes() != null) {
        Iterator<JParameter> paramIt = curMethod.method.getParams().iterator();
        if (curClass.classType.isEnumOrSubclass() != null) {
          // Skip past the enum args.
          paramIt.next();
          paramIt.next();
        }
        for (@SuppressWarnings("unused")
        ReferenceBinding argType : binding.syntheticEnclosingInstanceTypes()) {
          JParameter param = paramIt.next();
          call.addArg(param.makeRef(call.getSourceInfo()));
        }
      }
    }

    private void push(JNode node) {
      nodeStack.add(node);
    }

    private void pushBinaryOp(Expression x, JBinaryOperator op, Expression lhs, Expression rhs) {
      try {
        JType type = typeMap.get(x.resolvedType);
        SourceInfo info = makeSourceInfo(x);
        JExpression exprArg2 = pop(rhs);
        JExpression exprArg1 = pop(lhs);
        push(new JBinaryOperation(info, type, op, exprArg1, exprArg2));
      } catch (Throwable e) {
        throw translateException(x, e);
      }
    }

    private void pushInitializerMethodInfo(FieldDeclaration x, MethodScope scope) {
      JMethod initMethod;
      if (x.isStatic()) {
        initMethod = curClass.type.getClinitMethod();
      } else {
        initMethod = curClass.type.getInitMethod();
      }
      pushMethodInfo(new MethodInfo(initMethod, (JMethodBody) initMethod.getBody(), scope));
    }

    private void pushMethodInfo(MethodInfo newInfo) {
      methodStack.push(curMethod);
      curMethod = newInfo;
    }

    private void pushNewExpression(SourceInfo info, AllocationExpression x, Expression qualifier,
        List<JExpression> arguments, BlockScope scope) {
      TypeBinding typeBinding = x.resolvedType;
      if (typeBinding.constantPoolName() == null) {
        /*
         * Weird case: if JDT determines that this local class is totally
         * uninstantiable, it won't bother allocating a local name.
         */
        push(JNullLiteral.INSTANCE);
        return;
      }
      assert typeBinding.isClass() || typeBinding.isEnum();

      MethodBinding b = x.binding;
      assert b.isConstructor();
      JConstructor ctor = (JConstructor) typeMap.get(b);
      JMethodCall call = new JNewInstance(info, ctor);
      JExpression qualExpr = pop(qualifier);

      // Enums: hidden arguments for the name and id.
      if (x.enumConstant != null) {
        call.addArgs(getStringLiteral(info, x.enumConstant.name), JIntLiteral
            .get(x.enumConstant.binding.original().id));
      }

      // Synthetic args for inner classes
      ReferenceBinding targetBinding = (ReferenceBinding) b.declaringClass.erasure();
      boolean isNested = JdtUtil.isInnerClass(targetBinding);
      if (isNested) {
        // Synthetic this args for inner classes
        if (targetBinding.syntheticEnclosingInstanceTypes() != null) {
          ReferenceBinding checkedTargetType =
              targetBinding.isAnonymousType() ? (ReferenceBinding) targetBinding.superclass()
                  .erasure() : targetBinding;
          ReferenceBinding targetEnclosingType = checkedTargetType.enclosingType();
          for (ReferenceBinding argType : targetBinding.syntheticEnclosingInstanceTypes()) {
            argType = (ReferenceBinding) argType.erasure();
            if (qualifier != null && argType == targetEnclosingType) {
              call.addArg(qualExpr);
            } else {
              JExpression thisRef = resolveThisReference(info, argType, false, scope);
              call.addArg(thisRef);
            }
          }
        }
      }

      // Plain old regular user arguments
      call.addArgs(arguments);

      // Synthetic args for inner classes
      if (isNested) {
        // Synthetic locals for local classes
        if (targetBinding.syntheticOuterLocalVariables() != null) {
          for (SyntheticArgumentBinding arg : targetBinding.syntheticOuterLocalVariables()) {
            LocalVariableBinding targetVariable = arg.actualOuterLocalVariable;
            VariableBinding[] path = scope.getEmulationPath(targetVariable);
            assert path.length == 1;
            if (curMethod.scope.isInsideInitializer()
                && path[0] instanceof SyntheticArgumentBinding) {
              SyntheticArgumentBinding sb = (SyntheticArgumentBinding) path[0];
              JField field = curClass.syntheticFields.get(sb);
              assert field != null;
              call.addArg(makeInstanceFieldRef(info, field));
            } else if (path[0] instanceof LocalVariableBinding) {
              JExpression localRef = makeLocalRef(info, (LocalVariableBinding) path[0], curMethod);
              call.addArg(localRef);
            } else if (path[0] instanceof FieldBinding) {
              JField field = typeMap.get((FieldBinding) path[0]);
              assert field != null;
              call.addArg(makeInstanceFieldRef(info, field));
            } else {
              throw new InternalCompilerException("Unknown emulation path.");
            }
          }
        }
      }

      push(call);
    }

    /**
     * Don't process unreachable statements, because JDT doesn't always fully
     * resolve them, which can crash us.
     */
    private Statement[] reduceToReachable(Statement[] statements) {
      if (statements == null) {
        return null;
      }
      int reachableCount = 0;
      for (Statement statement : statements) {
        if ((statement.bits & ASTNode.IsReachable) != 0) {
          ++reachableCount;
        }
      }
      if (reachableCount == statements.length) {
        return statements;
      }
      Statement[] newStatments = new Statement[reachableCount];
      int index = 0;
      for (Statement statement : statements) {
        if ((statement.bits & ASTNode.IsReachable) != 0) {
          newStatments[index++] = statement;
        }
      }
      return newStatments;
    }

    private JExpression resolveNameReference(NameReference x, BlockScope scope) {
      SourceInfo info = makeSourceInfo(x);
      Binding binding = x.binding;
      if (isOptimizableCompileTimeConstant(binding)) {
        return getConstant(info, x.constant);
      }
      JExpression result = null;
      if (binding instanceof LocalVariableBinding) {
        LocalVariableBinding b = (LocalVariableBinding) binding;
        MethodScope nearestMethodScope =
            scope instanceof MethodScope ? (MethodScope) scope : scope.enclosingMethodScope();
        if ((x.bits & ASTNode.DepthMASK) != 0 || nearestMethodScope.isLambdaScope()) {
          VariableBinding[] path = scope.getEmulationPath(b);
          if (path == null) {
            /*
             * Don't like this, but in rare cases (e.g. the variable is only
             * ever used as an unnecessary qualifier) JDT provides no emulation
             * to the desired variable.
             */
            // throw new InternalCompilerException("No emulation path.");
            return null;
          }
          assert path.length == 1;
          if (curMethod.scope.isInsideInitializer()
              && path[0] instanceof SyntheticArgumentBinding) {
            SyntheticArgumentBinding sb = (SyntheticArgumentBinding) path[0];
            JField field = curClass.syntheticFields.get(sb);
            assert field != null;
            result = makeInstanceFieldRef(info, field);
          } else if (path[0] instanceof LocalVariableBinding) {
            result = makeLocalRef(info, (LocalVariableBinding) path[0], curMethod);
          } else if (path[0] instanceof FieldBinding) {
            FieldBinding fb = (FieldBinding) path[0];
            assert curClass.typeDecl.binding.isCompatibleWith(x.actualReceiverType.erasure());
            JField field = typeMap.get(fb);
            assert field != null;
            result = makeInstanceFieldRef(info, field);
          } else {
            throw new InternalCompilerException("Unknown emulation path.");
          }
        } else {
          result = makeLocalRef(info, b, curMethod);
        }
      } else if (binding instanceof FieldBinding) {
        FieldBinding b = ((FieldBinding) x.binding).original();
        JField field = typeMap.get(b);
        assert field != null;
        JExpression thisRef = null;
        if (!b.isStatic()) {
          thisRef =
              resolveThisReference(info, (ReferenceBinding) x.actualReceiverType, false, scope);
        }
        result = new JFieldRef(info, thisRef, field, curClass.type);
      } else {
        return null;
      }
      assert result != null;
      return result;
    }

    private JExpression maybeBoxOrUnbox(JExpression result, Expression x) {
      return maybeBoxOrUnbox(result, x.implicitConversion);
    }

    private JExpression synthesizeCallToOrdinal(BlockScope scope, SourceInfo info,
        JExpression expression) {
      ReferenceBinding javaLangEnum = scope.getJavaLangEnum();
      MethodBinding ordinal = javaLangEnum.getMethods(ORDINAL_)[0];
      expression = new JMethodCall(info, expression, typeMap.get(ordinal));
      return expression;
    }

    private void writeEnumValueOfMethod(JEnumType type, JMethod method, JMethod valuesMethod) {
      JField mapField;
      TypeBinding mapType;
      ReferenceBinding enumType = curCud.scope.getJavaLangEnum();
      {
        /*
         * Make an inner class to hold a lazy-init name-value map. We use a
         * class to take advantage of its clinit.
         *
         * class Map { $MAP = Enum.createValueOfMap(values()); }
         */
        SourceInfo info = type.getSourceInfo();
        JClassType mapClass = new JClassType(info, intern(type.getName() + "$Map"), false, true);
        mapClass.setSuperClass(javaLangObject);
        mapClass.setEnclosingType(type);
        newTypes.add(mapClass);

        MethodBinding[] createValueOfMapBindings = enumType.getMethods(CREATE_VALUE_OF_MAP_);
        if (createValueOfMapBindings.length == 0) {
          throw new RuntimeException(
              "Unexpectedly unable to access Enum.createValueOfMap via reflection. "
              + "Likely a dependency on the com.google.gwt.user.User module is missing.");
        }
        MethodBinding createValueOfMapBinding = createValueOfMapBindings[0];
        mapType = createValueOfMapBinding.returnType;

        mapField = new JField(info, "$MAP", mapClass, typeMap.get(mapType), true, Disposition.FINAL,
            AccessModifier.PRIVATE);
        mapClass.addField(mapField);

        JMethodCall call = new JMethodCall(info, null, typeMap.get(createValueOfMapBinding));
        call.addArg(new JMethodCall(info, null, valuesMethod));
        JFieldRef mapRef = new JFieldRef(info, null, mapField, mapClass);
        JDeclarationStatement declStmt = new JDeclarationStatement(info, mapRef, call);
        JMethod clinit =
            createSyntheticMethod(info, "$clinit", mapClass, JPrimitiveType.VOID, false, true,
                true, AccessModifier.PRIVATE);
        JBlock clinitBlock = ((JMethodBody) clinit.getBody()).getBlock();
        clinitBlock.addStmt(declStmt);
      }

      /*
       * return Enum.valueOf(Enum$Map.Map.$MAP, name);
       */
      {
        SourceInfo info = method.getSourceInfo();

        MethodBinding valueOfBinding =
            enumType.getExactMethod(VALUE_OF_, new TypeBinding[]{
                mapType, curCud.scope.getJavaLangString()}, curCud.scope);
        assert valueOfBinding != null;

        JFieldRef mapRef = new JFieldRef(info, null, mapField, type);
        JParameterRef nameRef = method.getParams().get(0).makeRef(info);
        JMethodCall call = new JMethodCall(info, null, typeMap.get(valueOfBinding));
        call.addArgs(mapRef, nameRef);
        JjsUtils.replaceMethodBody(method, call);
      }
    }

    private JCastOperation buildCastOperation(SourceInfo info, JType[] castTypes,
        JExpression expression) {
      return buildCastOperation(info, castTypes, expression, 0);
    }

    private JCastOperation buildCastOperation(SourceInfo info, JType[] castTypes,
        JExpression expression, int idx) {
      if (idx == castTypes.length - 1) {
        return new JCastOperation(info, castTypes[idx], expression);
      } else {
        return new JCastOperation(info, castTypes[idx],
            buildCastOperation(info, castTypes, expression, idx + 1));
      }
    }

    private JReferenceType[] processIntersectionCastType(IntersectionTypeBinding18 type) {
      JReferenceType[] castTypes = new JReferenceType[type.intersectingTypes.length];
      int i = 0;
      for (ReferenceBinding intersectingTypeBinding : type.intersectingTypes) {
        JType intersectingType = typeMap.get(intersectingTypeBinding);
        assert (intersectingType instanceof JReferenceType);
        castTypes[i++] = ((JReferenceType) intersectingType);
      }
      return castTypes;
    }

    private JType[] processCastType(TypeBinding type) {
      if (type instanceof IntersectionTypeBinding18) {
        return processIntersectionCastType((IntersectionTypeBinding18) type);
      } else {
        return new JType[] {typeMap.get(type)};
      }
    }

    private JInterfaceType[] processIntersectionTypeForLambda(IntersectionTypeBinding18 type,
        BlockScope scope, String samSignature) {
      List<JInterfaceType> interfaces = Lists.newArrayList();
      for (ReferenceBinding intersectingTypeBinding : type.intersectingTypes) {
        if (shouldImplements(intersectingTypeBinding, scope, samSignature)) {
          JType intersectingType = typeMap.get(intersectingTypeBinding);
          assert (intersectingType instanceof JInterfaceType);
          interfaces.add(((JInterfaceType) intersectingType));
        }
      }
      return Iterables.toArray(interfaces, JInterfaceType.class);
    }

    private boolean isFunctionalInterfaceWithMethod(ReferenceBinding referenceBinding, Scope scope,
        String samSignature) {
      if (!referenceBinding.isInterface()) {
        return false;
      }
      MethodBinding abstractMethod = referenceBinding.getSingleAbstractMethod(scope, false);
      return abstractMethod != null && abstractMethod.isValidBinding()
          && JdtUtil.signature(abstractMethod).equals(samSignature);
    }

    private boolean isInterfaceHasNoAbstractMethod(ReferenceBinding referenceBinding, Scope scope) {
      List<MethodBinding> abstractMethods = getInterfaceAbstractMethods(referenceBinding, scope);
      return abstractMethods != null && abstractMethods.size() == 0;
    }

    private boolean shouldImplements(ReferenceBinding referenceBinding, Scope scope,
        String samSignature) {
      return isFunctionalInterfaceWithMethod(referenceBinding, scope, samSignature)
          || isInterfaceHasNoAbstractMethod(referenceBinding, scope);
    }

    /**
     * Collect all abstract methods in an interface and its super interfaces.
     *
     * In the case of multiple inheritance like this,
     *
     * interface I {m();}
     * interface J {default m();}
     * interface K extends I, J{}
     *
     * the abstract methods of K include m();
     */
    private List<MethodBinding> getInterfaceAbstractMethods(ReferenceBinding referenceBinding,
        Scope scope) {
      if (!referenceBinding.isInterface() || !referenceBinding.isValidBinding()) {
        return null;
      }
      List<MethodBinding> abstractMethods = Lists.newLinkedList();

      // add all abstract methods from super interfaces.
      for (ReferenceBinding superInterface : referenceBinding.superInterfaces()) {
        List<MethodBinding> abstractMethodsFromSupers =
            getInterfaceAbstractMethods(superInterface, scope);
        if (abstractMethodsFromSupers != null && abstractMethodsFromSupers.size() > 0) {
          abstractMethods.addAll(abstractMethodsFromSupers);
        }
      }
      for (MethodBinding method : referenceBinding.methods()) {
        if (method == null || method.isStatic() || method.redeclaresPublicObjectMethod(scope)) {
          continue;
        }
        // remove the overridden methods in the super interfaces.
        for (MethodBinding abstractMethodFromSupers : abstractMethods) {
          if (MethodVerifier.doesMethodOverride(method, abstractMethodFromSupers,
              scope.environment())) {
            abstractMethods.remove(abstractMethodFromSupers);
          }
        }
        // add method to abstract methods if it is not a default method.
        if (!method.isDefaultMethod()) {
          abstractMethods.add(method);
        }
      }
      return abstractMethods;
    }
  }

  private <T extends JType> Iterable<T> mapTypes(TypeBinding[] types) {
    return FluentIterable.from(Arrays.asList(types)).transform(
        new Function<TypeBinding, T>() {
          @Override
          public T apply(TypeBinding typeBinding) {
            return (T) typeMap.get(typeBinding.erasure());
          }
        });
  }

  static class ClassInfo {
    public final JClassType classType;
    public final ClassScope scope;
    public final Map<SyntheticArgumentBinding, JField> syntheticFields = Maps.newIdentityHashMap();
    public final JDeclaredType type;
    public final TypeDeclaration typeDecl;

    public ClassInfo(JDeclaredType type, TypeDeclaration x) {
      this.type = type;
      this.classType = (type instanceof JClassType) ? (JClassType) type : null;
      this.typeDecl = x;
      this.scope = x.scope;
    }

    public JDeclaredType getClassOrInterface() {
      return classType == null ? type : classType;
    }
  }

  static class CudInfo {
    public final CompilationUnitScope scope;
    public final int[] separatorPositions;
    public final CompilationUnitDeclaration cud;

    public CudInfo(CompilationUnitDeclaration cud) {
      separatorPositions = cud.compilationResult().getLineSeparatorPositions();
      scope = cud.scope;
      this.cud = cud;
    }
  }

  static class MethodInfo {
    public final JMethodBody body;
    public final Map<String, JLabel> labels = Maps.newHashMap();
    public final Map<LocalVariableBinding, JVariable> locals = Maps.newIdentityHashMap();
    public final JMethod method;
    public final MethodScope scope;

    public MethodInfo(JMethod method, JMethodBody methodBody, MethodScope methodScope) {
      this.method = method;
      this.body = methodBody;
      this.scope = methodScope;
    }
  }

  /**
   * Manually tracked version count.
   */
  private static final long AST_VERSION = 3;
  private static final int MAX_INLINEABLE_ENUM_SIZE = 10;

  private static final String CREATE_VALUE_OF_MAP_METHOD_NAME = "createValueOfMap";
  private static final String LENGTH_FIELD_NAME = "length";

  private static final char[] CREATE_VALUE_OF_MAP_ = CREATE_VALUE_OF_MAP_METHOD_NAME.toCharArray();
  private static final char[] VALUE_OF_ = VALUE_OF_METHOD_NAME.toCharArray();
  private static final char[] VALUES_ = VALUES_METHOD_NAME.toCharArray();
  private static final char[] ORDINAL_ = ORDINAL_METHOD_NAME.toCharArray();
  private static final char[] NEXT_ = NEXT_METHOD_NAME.toCharArray();
  private static final char[] ITERATOR_ = ITERATOR_METHOD_NAME.toCharArray();
  private static final char[] HAS_NEXT_ = HAS_NEXT_METHOD_NAME.toCharArray();

  private static final TypeBinding[] NO_TYPES = new TypeBinding[0];
  private static final Interner<String> stringInterner = StringInterner.get();

  static {
    InternalCompilerException.preload();
  }

  /**
   * Returns a serialization version number. Used to determine if the AST
   * contained within cached compilation units is compatible with the current
   * version of GWT.
   */
  public static long getSerializationVersion() {
    // TODO(zundel): something much awesomer.
    return AST_VERSION;
  }

  static Disposition getFieldDisposition(FieldBinding binding) {
    Disposition disposition;
    if (isCompileTimeConstant(binding)) {
      disposition = Disposition.COMPILE_TIME_CONSTANT;
    } else if (binding.isFinal()) {
      disposition = Disposition.FINAL;
    } else if (binding.isVolatile()) {
      disposition = Disposition.VOLATILE;
    } else {
      disposition = Disposition.NONE;
    }
    return disposition;
  }

  static String intern(char[] cs) {
    return intern(String.valueOf(cs));
  }

  static String intern(String s) {
    return stringInterner.intern(s);
  }

  /**
   * Creates the statement that will constitute the method body implementing a lambda expression.
   * <p>
   * Lambda expressions might be represented in the JDT AST as Java expressions or Java statements.
   */
  private static JStatement getOrCreateLambdaStatement(JNode node) {
    if (node instanceof JStatement) {
      return (JStatement) node;
    }
    assert node instanceof JExpression;
    JExpression expression = (JExpression) node;
    return JjsUtils.makeMethodEndStatement(expression.getType(), expression);
  }

  private boolean isOptimizableCompileTimeConstant(Binding binding) {
    if (binding instanceof LocalVariableBinding &&
        ((LocalVariableBinding) binding).constant() != Constant.NotAConstant) {
      // Propagate constants in local variables regardless whether we are optimizing compile time
      // constants or not. This is necessary as the JDT will not compute an emulation path for a
      // local constant referred in a nested class closure.
      return true;
    }
    if (!(binding instanceof FieldBinding)) {
      return false;
    }
    FieldBinding fieldBinding = (FieldBinding) binding;
    return (compilerContext.getOptions().shouldJDTInlineCompileTimeConstants()
        || isBinaryBinding(fieldBinding.declaringClass)) &&
        isCompileTimeConstant(fieldBinding);
  }

  private static boolean isCompileTimeConstant(FieldBinding binding) {
    assert !binding.isFinal() || !binding.isVolatile();
    boolean isCompileTimeConstant = binding.isStatic() && binding.isFinal() &&
        binding.constant() != Constant.NotAConstant;
    assert !isCompileTimeConstant || binding.type.isBaseType() ||
        (binding.type.id == TypeIds.T_JavaLangString);
    return isCompileTimeConstant;
  }

  private boolean isBinaryBinding(ReferenceBinding binding) {
    if (binding instanceof BinaryTypeBinding) {
      // Is it really a BinaryBinding? If a source resource exists, the BinaryTypeBinding is
      // considered a source type binding.
      return !compilerContext.getMinimalRebuildCache().isSourceCompilationUnit(
          JdtUtil.getDefiningCompilationUnitType(binding));
    }
    return false;
  }

  CudInfo curCud = null;

  JClassType javaLangClass = null;
  JClassType javaLangObject = null;
  JClassType javaLangString = null;
  JClassType javaLangThrowable = null;

  Map<MethodDeclaration, JsniMethod> jsniMethods;

  Map<String, Binding> jsniRefs;

  final ReferenceMapper typeMap = new ReferenceMapper();

  private final AstVisitor astVisitor = new AstVisitor();

  private List<JDeclaredType> newTypes;

  private String sourceMapPath;

  private CompilerContext compilerContext;

  private boolean generateJsInteropExports;

  private WhitelistRegexFilter jsInteropExportFilter;

  /**
   * Externalized class and method form for Exceptions.safeClose() to provide support
   * for try-with-resources.
   *
   * The externalized form will be resolved during AST stitching.
   */
  private static JMethod SAFE_CLOSE_METHOD =
      JMethod.getExternalizedMethod("com.google.gwt.lang.Exceptions",
      "safeClose(Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)Ljava/lang/Throwable;", true);

  private static JMethod CAST_GET_CLASS_METHOD =
      JMethod.getExternalizedMethod("com.google.gwt.lang.Cast",
      "getClass(Ljava/lang/Object;)Ljava/lang/Class;", true);

  private List<JDeclaredType> processImpl() {
    CompilationUnitDeclaration cud = curCud.cud;
    if (cud.types == null) {
      return Collections.emptyList();
    }

    for (TypeDeclaration typeDecl : cud.types) {
      createTypes(typeDecl);
    }

    // Now that types exist, cache Object, String, etc.
    javaLangObject = (JClassType) typeMap.get(cud.scope.getJavaLangObject());
    javaLangString = (JClassType) typeMap.get(cud.scope.getJavaLangString());
    javaLangClass = (JClassType) typeMap.get(cud.scope.getJavaLangClass());
    javaLangThrowable = (JClassType) typeMap.get(cud.scope.getJavaLangThrowable());

    for (TypeDeclaration typeDecl : cud.types) {
      // Resolve super type / interface relationships.
      resolveTypeRefs(typeDecl);
    }
    for (TypeDeclaration typeDecl : cud.types) {
      // Create fields and empty methods.
      createMembers(typeDecl);
    }
    for (TypeDeclaration typeDecl : cud.types) {
      // Build the code.
      typeDecl.traverse(astVisitor, cud.scope);
    }
    return newTypes;
  }

  private GwtAstBuilder(CompilationUnitDeclaration cud, String sourceMapPath,
      Map<MethodDeclaration, JsniMethod> jsniMethods, Map<String, Binding> jsniRefs,
      CompilerContext compilerContext) {
    this.sourceMapPath = sourceMapPath;
    this.jsniRefs = jsniRefs;
    this.jsniMethods = jsniMethods;
    this.compilerContext = compilerContext;
    this.generateJsInteropExports = compilerContext.getOptions().shouldGenerateJsInteropExports();
    this.jsInteropExportFilter = compilerContext.getOptions().getJsInteropExportFilter();
    this.newTypes = Lists.newArrayList();
    this.curCud = new CudInfo(cud);
  }

  private boolean shouldExport(JMember member) {
    return generateJsInteropExports
        && (jsInteropExportFilter.isEmpty()
            || jsInteropExportFilter.isIncluded(member.getQualifiedName()));
  }

  /**
   * Builds all the GWT AST nodes that correspond to one Java source file.
   *
   * @param cud The compiled form of the Java source from the JDT.
   * @param sourceMapPath the path that should be included in a sourcemap.
   * @param jsniMethods Native methods to add to the AST.
   * @param jsniRefs Map from JSNI references to their JDT definitions.
   * @param compilerContext the compiler context.
   * @return All the types seen in this source file.
   */
  public static List<JDeclaredType> process(CompilationUnitDeclaration cud, String sourceMapPath,
      Map<MethodDeclaration, JsniMethod> jsniMethods, Map<String, Binding> jsniRefs,
      CompilerContext compilerContext) {
    return new GwtAstBuilder(cud, sourceMapPath, jsniMethods, jsniRefs, compilerContext)
        .processImpl();
  }

  SourceInfo makeSourceInfo(AbstractMethodDeclaration x) {
    int startLine =
        Util.getLineNumber(x.sourceStart, curCud.separatorPositions, 0,
            curCud.separatorPositions.length - 1);
    return SourceOrigin.create(x.sourceStart, x.bodyEnd, startLine, sourceMapPath);
  }

  SourceInfo makeSourceInfo(ASTNode x) {
    int startLine =
        Util.getLineNumber(x.sourceStart, curCud.separatorPositions, 0,
            curCud.separatorPositions.length - 1);
    return SourceOrigin.create(x.sourceStart, x.sourceEnd, startLine, sourceMapPath);
  }

  InternalCompilerException translateException(ASTNode node, 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 constructing Java AST", e);
    }
    if (node != null) {
      ice.addNode(node.getClass().getName(), node.toString(), makeSourceInfo(node));
    }
    return ice;
  }

  private void createField(FieldDeclaration x) {
    if (x instanceof Initializer) {
      return;
    }
    SourceInfo info = makeSourceInfo(x);
    FieldBinding binding = x.binding;
    JType type = typeMap.get(binding.type);
    JDeclaredType enclosingType = (JDeclaredType) typeMap.get(binding.declaringClass);

    JField field;
    if (x.initialization != null && x.initialization instanceof AllocationExpression
        && ((AllocationExpression) x.initialization).enumConstant != null) {
      field = new JEnumField(info, intern(binding.name), binding.original().id,
          (JEnumType) enclosingType, (JClassType) type, AccessModifier.fromFieldBinding(binding));
    } else {
      field =
          new JField(info, intern(binding.name), enclosingType, type, binding.isStatic(),
              getFieldDisposition(binding), AccessModifier.fromFieldBinding(binding));
    }
    enclosingType.addField(field);
    JsInteropUtil.maybeSetJsInteropProperties(field, shouldExport(field), x.annotations);
    processSuppressedWarnings(field, x.annotations);
    typeMap.setField(binding, field);
  }

  private void createMembers(TypeDeclaration x) {
    SourceTypeBinding binding = x.binding;
    JDeclaredType type = (JDeclaredType) typeMap.get(binding);
    SourceInfo info = type.getSourceInfo();
    try {
      /**
       * 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.
       */
      assert type.getMethods().size() == CLINIT_METHOD_INDEX;
      createSyntheticMethod(info, CLINIT_METHOD_NAME, type, JPrimitiveType.VOID, false, true, true,
          AccessModifier.PRIVATE);

      if (type instanceof JClassType) {
        assert type.getMethods().size() == INIT_METHOD_INDEX;
        createSyntheticMethod(info, INIT_NAME_METHOD_NAME, type, JPrimitiveType.VOID, false, false,
            true, AccessModifier.PRIVATE);

        // Add a getClass() implementation for all non-Object, non-String classes.
        if (isSyntheticGetClassNeeded(x, type)) {
          assert type.getMethods().size() == GET_CLASS_METHOD_INDEX;
          createSyntheticMethod(info, GET_CLASS_METHOD_NAME, type, javaLangClass, type.isAbstract(),
              false, false, AccessModifier.PUBLIC);
        }
      }

      if (type instanceof JEnumType) {
        {
          assert type.getMethods().size()
              == getEnumMethodsStartIndex(type) + VALUE_OF_METHOD_OFFSET;
          MethodBinding valueOfBinding =
              binding.getExactMethod(VALUE_OF_,
                  new TypeBinding[]{x.scope.getJavaLangString()}, curCud.scope);
          assert valueOfBinding != null;
          createMethodFromBinding(info, valueOfBinding, new String[] {"name"});
        }
        {
          assert type.getMethods().size()
              == getEnumMethodsStartIndex(type) + VALUES_METHOD_OFFSET;

          MethodBinding valuesBinding = binding.getExactMethod(VALUES_, NO_TYPES, curCud.scope);
          assert valuesBinding != null;
          createMethodFromBinding(info, valuesBinding, null);
        }
      }

      if (x.fields != null) {
        for (FieldDeclaration field : x.fields) {
          createField(field);
        }
      }

      if (x.methods != null) {
        for (AbstractMethodDeclaration method : x.methods) {
          createMethod(method);
        }
      }

      if (x.memberTypes != null) {
        for (TypeDeclaration memberType : x.memberTypes) {
          createMembers(memberType);
        }
      }
    } catch (Throwable e) {
      throw getInternalCompilerException(x, e);
    }
  }

  private static boolean isSyntheticGetClassNeeded(
      TypeDeclaration typeDeclaration, JDeclaredType type) {
    // TODO(rluble): We should check whether getClass is implemented by type and only
    // instead of blacklisting.
    return type.getSuperClass() != null && !JdtUtil.isJsoSubclass(typeDeclaration.binding)
        && !type.isJsNative();
  }

  private static final int VALUE_OF_METHOD_OFFSET = 0;
  private static final int VALUES_METHOD_OFFSET = 1;

  private static int getEnumMethodsStartIndex(JType type) {
    assert type instanceof JEnumType;
    if (type.isJsNative()) {
      return GET_CLASS_METHOD_INDEX;
    }
    return GET_CLASS_METHOD_INDEX + 1;
  }

  private void createMethod(AbstractMethodDeclaration x) {
    if (x instanceof Clinit) {
      return;
    }
    SourceInfo info = makeSourceInfo(x);
    MethodBinding b = x.binding;
    ReferenceBinding declaringClass = (ReferenceBinding) b.declaringClass.erasure();
    Set<String> alreadyNamedVariables = Sets.newHashSet();
    JDeclaredType enclosingType = (JDeclaredType) typeMap.get(declaringClass);
    assert !enclosingType.isExternal();
    JMethod method;
    boolean isNested = JdtUtil.isInnerClass(declaringClass);
    if (x.isConstructor()) {
      method =
          new JConstructor(info, (JClassType) enclosingType, AccessModifier.fromMethodBinding(b));
      if (x.isDefaultConstructor()) {
        ((JConstructor) method).setDefaultConstructor();
      }
      if (x.binding.declaringClass.isEnum()) {
        // Enums have hidden arguments for name and value
        method.createFinalParameter(info, "enum$name", typeMap.get(x.scope.getJavaLangString()));
        method.createFinalParameter(info, "enum$ordinal", JPrimitiveType.INT);
      }
      // add synthetic args for outer this
      if (isNested) {
        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(info, arg, argName, method, false);
            alreadyNamedVariables.add(argName);
          }
        }
      }
    } else {
      method =
          new JMethod(info, intern(b.selector), enclosingType, typeMap.get(b.returnType), b
              .isAbstract(), b.isStatic(), b.isFinal(), AccessModifier.fromMethodBinding(b));
    }

    // User args.
    createParameters(method, x);

    if (x.isConstructor()) {
      if (isNested) {
        // 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(info, arg, argName, method, false);
            alreadyNamedVariables.add(argName);
          }
        }
      }
    }

    mapExceptions(method, b);

    if (b.isSynthetic()) {
      method.setSynthetic();
    }

    if (b.isDefaultMethod()) {
      method.setDefaultMethod(true);
    }

    enclosingType.addMethod(method);
    processAnnotations(x, method);
    typeMap.setMethod(b, method);
  }

  private void processAnnotations(AbstractMethodDeclaration x,
      JMethod method) {
    maybeAddMethodSpecialization(x, method);
    maybeSetInliningMode(x, method);
    maybeSetHasNoSideEffects(x, method);
    JsInteropUtil.maybeSetJsInteropProperties(method, shouldExport(method), x.annotations);
    processSuppressedWarnings(method, x.annotations);
  }

  private void processAnnotations(JParameter parameter, Annotation... annotations) {
    JsInteropUtil.maybeSetJsInteropProperties(parameter, annotations);
    processSuppressedWarnings(parameter, annotations);
  }

  private void processSuppressedWarnings(CanHaveSuppressedWarnings x, Annotation... annotations) {
    x.setSuppressedWarnings(JdtUtil.getSuppressedWarnings(annotations));
  }

  private static boolean isUncheckedGenericMethodCall(MessageSend messageSend) {
    if (messageSend.binding.genericMethod() != null) {
      return JdtUtil.getAnnotationByName(messageSend.binding().getAnnotations(),
              "javaemul.internal.annotations.UncheckedCast") != null;
    }
    return false;
  }

  private static void maybeSetInliningMode(AbstractMethodDeclaration x, JMethod method) {
    if (JdtUtil.getAnnotationByName(
        x.annotations, "javaemul.internal.annotations.DoNotInline") != null) {
      method.setInliningMode(InliningMode.DO_NOT_INLINE);
    } else if (JdtUtil.getAnnotationByName(
        x.annotations, "javaemul.internal.annotations.ForceInline") != null) {
      method.setInliningMode(InliningMode.FORCE_INLINE);
    }
  }

  private static void maybeSetHasNoSideEffects(AbstractMethodDeclaration x, JMethod method) {
    if (JdtUtil.getAnnotationByName(
        x.annotations, "javaemul.internal.annotations.HasNoSideEffects") != null) {
      method.setHasSideEffects(false);
    }
  }

  private void maybeAddMethodSpecialization(AbstractMethodDeclaration x, JMethod method) {
    AnnotationBinding specializeAnnotation = JdtUtil.getAnnotationByName(
        x.annotations, "javaemul.internal.annotations.SpecializeMethod");
    if (specializeAnnotation == null) {
      return;
    }

    TypeBinding[] params =
        JdtUtil.getAnnotationParameterTypeBindingArray(specializeAnnotation, "params");
    assert params != null : "params is a mandatory field";
    List<JType> paramTypes = Lists.newArrayList(mapTypes(params));

    TypeBinding returns =
        JdtUtil.getAnnotationParameterTypeBinding(specializeAnnotation, "returns");
    JType returnsType = returns == null ? null : typeMap.get(returns);

    String targetMethod = JdtUtil.getAnnotationParameterString(specializeAnnotation, "target");
    assert targetMethod != null : "target is a mandatory parameter";

    method.setSpecialization(paramTypes, returnsType, targetMethod);
  }

  private void createParameter(SourceInfo info, LocalVariableBinding binding, boolean isVarargs,
      JMethod method, Annotation... annotations) {
    createParameter(info, binding, intern(binding.name), method, isVarargs, annotations);
  }

  private void createParameter(SourceInfo info, LocalVariableBinding binding, String name,
      JMethod method, boolean isVarargs, Annotation... annotations) {
    JParameter parameter =
        method.createParameter(info, name, typeMap.get(binding.type), binding.isFinal(), isVarargs);
    processAnnotations(parameter, annotations);
  }

  private void createParameters(JMethod method, AbstractMethodDeclaration x) {
    if (x.arguments != null) {
      for (Argument argument : x.arguments) {
        SourceInfo info = makeSourceInfo(argument);
        LocalVariableBinding binding = argument.binding;
        boolean isVarargs = x.binding.isVarargs()
            && argument == x.arguments[x.arguments.length - 1];
        createParameter(info, binding, isVarargs, method, argument.annotations);
      }
    }
    method.freezeParamTypes();
  }

  private JMethod createSyntheticMethod(SourceInfo info, String name, JDeclaredType enclosingType,
      JType returnType, boolean isAbstract, boolean isStatic, boolean isFinal,
      AccessModifier access, JStatement ... statements) {
    JMethod method =
        new JMethod(info, name, enclosingType, returnType, isAbstract, isStatic, isFinal, access);
    method.freezeParamTypes();
    method.setSynthetic();
    JMethodBody body = new JMethodBody(info);
    for (JStatement statement : statements) {
      body.getBlock().addStmt(statement);
    }
    method.setBody(body);
    enclosingType.addMethod(method);
    return method;
  }

  private JMethod createMethodFromBinding(SourceInfo info, MethodBinding binding,
      String[] paramNames) {
    JMethod method = typeMap.createMethod(info, binding, paramNames);
    assert !method.isExternal();
    method.setBody(new JMethodBody(info));
    JsInteropUtil.maybeSetJsInteropProperties(method, shouldExport(method));
    typeMap.setMethod(binding, method);
    return method;
  }

  private void createTypes(TypeDeclaration x) {
    SourceInfo info = makeSourceInfo(x);
    try {
      SourceTypeBinding binding = x.binding;
      String name;
      if (binding instanceof LocalTypeBinding) {
        char[] localName = binding.constantPoolName();
        name = new String(localName).replace('/', '.');
      } else {
        name = JdtUtil.asDottedString(binding.compoundName);
      }
      name = intern(name);

      JDeclaredType type;
      if (binding.isClass()) {
        type = new JClassType(info, name, binding.isAbstract(), binding.isFinal());
      } else if (binding.isInterface() || binding.isAnnotationType()) {
        type = new JInterfaceType(info, name);
      } else if (binding.isEnum()) {
        if (binding.isAnonymousType()) {
          // Don't model an enum subclass as a JEnumType.
          type = new JClassType(info, name, false, true);
        } else {
          type = new JEnumType(info, name, binding.isAbstract());
        }
      } else {
        throw new InternalCompilerException("ReferenceBinding is not a class, interface, or enum.");
      }
      JsInteropUtil.maybeSetJsInteropProperties(type, x.annotations);
      processSuppressedWarnings(type, x.annotations);
      JdtUtil.setClassDispositionFromBinding(binding, type);
      typeMap.setSourceType(binding, type);
      newTypes.add(type);
      if (x.memberTypes != null) {
        for (TypeDeclaration memberType : x.memberTypes) {
          createTypes(memberType);
        }
      }
    } catch (Throwable e) {
      InternalCompilerException ice = translateException(null, e);
      StringBuffer sb = new StringBuffer();
      x.printHeader(0, sb);
      ice.addNode(x.getClass().getName(), sb.toString(), info);
      throw ice;
    }
  }

  private void mapExceptions(JMethod method, MethodBinding binding) {
    for (ReferenceBinding thrownBinding : binding.thrownExceptions) {
      JClassType type = (JClassType) typeMap.get(thrownBinding);
      method.addThrownException(type);
    }
  }

  private void resolveTypeRefs(TypeDeclaration x) {
    SourceTypeBinding binding = x.binding;
    JDeclaredType type = (JDeclaredType) typeMap.get(binding);
    try {
      ReferenceBinding superClassBinding = binding.superclass();
      if (type instanceof JClassType && superClassBinding != null) {
        assert (binding.superclass().isClass() || binding.superclass().isEnum());
        JClassType superClass = (JClassType) typeMap.get(superClassBinding);
        ((JClassType) type).setSuperClass(superClass);
      }

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

      ReferenceBinding enclosingBinding = binding.enclosingType();
      if (enclosingBinding != null) {
        type.setEnclosingType((JDeclaredType) typeMap.get(enclosingBinding));
      }
      if (x.memberTypes != null) {
        for (TypeDeclaration memberType : x.memberTypes) {
          resolveTypeRefs(memberType);
        }
      }
    } catch (Throwable e) {
      throw getInternalCompilerException(x, e);
    }
  }

  private InternalCompilerException getInternalCompilerException(TypeDeclaration x, Throwable e) {
    JDeclaredType type = (JDeclaredType) typeMap.get(x.binding);
    InternalCompilerException ice = translateException(null, e);
    StringBuffer sb = new StringBuffer();
    x.printHeader(0, sb);
    ice.addNode(x.getClass().getName(), sb.toString(), type.getSourceInfo());
    return ice;
  }

  /**
   * Returns the list of expressions as a single expression; returns {@code null} if the list
   * is empty.
   */
  private static JExpression singleExpressionFromExpressionList(SourceInfo info,
      List<JExpression> incrementsExpressions) {
    switch (incrementsExpressions.size()) {
      case 0:
        return null;
      case 1:
        return incrementsExpressions.get(0);
      default:
        return new JMultiExpression(info, incrementsExpressions);
    }
  }

  private boolean hasQualifier(ReferenceExpression x) {
    return !x.isTypeAccess();
  }

  private TypeBinding getCollectionElementTypeBinding(ForeachStatement x) {
    return (TypeBinding) accessPrivateField(JdtPrivateHacks.collectionElementTypeField, x);
  }

  private Object accessPrivateField(Field field, ASTNode astNode) {
    try {
      return field.get(astNode);
    } catch (IllegalAccessException e) {
      throw translateException(astNode, e);
    }
  }

  static class JdtPrivateHacks {
    /**
     * Reflective access to {@link ForeachStatement#collectionElementType}.
     */
    private static final Field collectionElementTypeField;

    static {
      try {
        collectionElementTypeField =
            ForeachStatement.class.getDeclaredField("collectionElementType");
        collectionElementTypeField.setAccessible(true);
      } catch (Exception e) {
        throw new RuntimeException(
            "Unexpectedly unable to access ForeachStatement.collectionElementType via reflection",
            e);
      }
    }
  }
}
