/*
 * 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.core.compiler.CharOperation;
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 = popCallArgs(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 = pop(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 = pop(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 = popCallArgs(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 = simplify((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 = popCallArgs(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)
              ? maybeInsertUnsafeTypeCoersion(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 = popCallArgs(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).original();

      // Get the interface method is binds to
      JMethod interfaceMethod = typeMap.get(samBinding);
      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() && instance == null &&
          samMethod.getParams().size() == referredMethod.getParams().size() + 1) {
        // 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
      if (referredMethodBinding.isVarargs() && !samBinding.parameters[varArg].isArrayType()) {
        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;
        // The method declared in the functional interface might have more 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.
        TypeBinding samParameterBinding =
            samBinding.parameters[paramNumber
                + (samBinding.parameters.length - referredMethodBinding.parameters.length)];
        // 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,
            samBinding.returnType);
        samMethodBody.getBlock().addStmt(simplify(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()) {
        int implicitConversion = (fromType.id & TypeIds.IMPLICIT_CONVERSION_MASK) << 4;
        implicitConversion = implicitConversion | TypeIds.BOXING;
        return box(expr, implicitConversion);
      }

      if (!fromType.isBaseType() && toType.isBaseType()) {
        int implicitConversion = (toType.id & TypeIds.IMPLICIT_CONVERSION_MASK) << 4;
        implicitConversion = implicitConversion | TypeIds.UNBOXING;
        return unbox(expr, implicitConversion);
      }

      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 = simplify(result, x);
      return result;
    }

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

      List<T> result = (List<T>) popList(Collections2.filter(Arrays.asList(expressions),
          Predicates.notNull()).size());

      for (int i = 0; i < result.size(); i++) {
        result.set(i, (T) simplify(result.get(i), expressions[i]));
      }
      return result;
    }

    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 simplify((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) simplify((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, int implicitConversion) {
      int typeId = (implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
      ClassScope scope = curClass.scope;
      BaseTypeBinding primitiveType = (BaseTypeBinding) TypeBinding.wellKnownType(scope, typeId);
      ReferenceBinding boxType = (ReferenceBinding) scope.boxing(primitiveType);
      MethodBinding valueOfMethod = boxType.getExactMethod(VALUE_OF_,
          new TypeBinding[]{primitiveType}, scope.compilationUnitScope());
      assert valueOfMethod != null;

      // 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);
      }

      JMethod boxMethod = typeMap.get(valueOfMethod);
      JMethodCall call = new JMethodCall(original.getSourceInfo(), null, boxMethod);
      call.addArg(original);
      return call;
    }

    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) {
      if (implicitConversion != -1) {
        if ((implicitConversion & TypeIds.BOXING) != 0) {
          return box(original, implicitConversion);
        } else if ((implicitConversion & TypeIds.UNBOXING) != 0) {
          return unbox(original, 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 maybeInsertUnsafeTypeCoersion(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> popCallArgs(SourceInfo info, Expression[] jdtArgs,
        MethodBinding binding) {
      List<JExpression> args = pop(jdtArgs);
      if (!binding.isVarargs()) {
        return args;
      }

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

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

      // See if there's a single varArg which is already an array.
      if (args.size() == params.length) {
        if (jdtArgs[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 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 simplify(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 JExpression unbox(JExpression original, int implicitConversion) {
      int compileTypeId = implicitConversion & TypeIds.COMPILE_TYPE_MASK;
      ClassScope scope = curClass.scope;
      TypeBinding targetBinding = TypeBinding.wellKnownType(scope, compileTypeId);
      if (!(targetBinding instanceof BaseTypeBinding)) {
        // Direct cast from non-boxed-type reference type to a primitive type,
        // wrap with a cast operation of the (boxed) expected type.
        int runtimeTypeId = (implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
        TypeBinding runtimeTypeBinding = TypeBinding.wellKnownType(scope, runtimeTypeId);
        ReferenceBinding boxType = (ReferenceBinding) scope.boxing(runtimeTypeBinding);
        original =
            new JCastOperation(original.getSourceInfo(), typeMap.get(boxType), original);
        targetBinding = runtimeTypeBinding;
        assert (targetBinding instanceof BaseTypeBinding);
      }

      BaseTypeBinding primitiveType = (BaseTypeBinding) targetBinding;

      ReferenceBinding boxType = (ReferenceBinding) scope.boxing(primitiveType);
      char[] selector = CharOperation.concat(primitiveType.simpleName, VALUE_SUFFIX_);
      MethodBinding valueMethod =
          boxType.getExactMethod(selector, NO_TYPES, scope.compilationUnitScope());
      assert valueMethod != null;
      JMethod unboxMethod = typeMap.get(valueMethod);
      JMethodCall call = new JMethodCall(original.getSourceInfo(), original, unboxMethod);
      return call;
    }

    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 String VALUE_SUFFIX = "Value";

  private static final char[] CREATE_VALUE_OF_MAP_ = CREATE_VALUE_OF_MAP_METHOD_NAME.toCharArray();
  private static final char[] VALUE_SUFFIX_ = VALUE_SUFFIX.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 (Boolean) accessPrivateField(JdtPrivateHacks.haveReceiverField, x);
  }

  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;
    /**
     * Reflective access to {@link ReferenceExpression#haveReceiver}.
     */
    private static final Field haveReceiverField;

    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);
      }

      try {
        haveReceiverField = ReferenceExpression.class.getDeclaredField("haveReceiver");
        haveReceiverField.setAccessible(true);
      } catch (Exception e) {
        throw new RuntimeException(
            "Unexpectedly unable to access ReferenceExpression.haveReceiver via reflection", e);
      }
    }
  }
}
