package org.checkerframework.framework.util;

import com.github.javaparser.ParseProblemException;
import com.github.javaparser.ast.ArrayCreationLevel;
import com.github.javaparser.ast.expr.ArrayAccessExpr;
import com.github.javaparser.ast.expr.ArrayCreationExpr;
import com.github.javaparser.ast.expr.BinaryExpr;
import com.github.javaparser.ast.expr.BooleanLiteralExpr;
import com.github.javaparser.ast.expr.CharLiteralExpr;
import com.github.javaparser.ast.expr.ClassExpr;
import com.github.javaparser.ast.expr.DoubleLiteralExpr;
import com.github.javaparser.ast.expr.EnclosedExpr;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.FieldAccessExpr;
import com.github.javaparser.ast.expr.IntegerLiteralExpr;
import com.github.javaparser.ast.expr.LongLiteralExpr;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.NullLiteralExpr;
import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.expr.SuperExpr;
import com.github.javaparser.ast.expr.ThisExpr;
import com.github.javaparser.ast.expr.UnaryExpr;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.visitor.GenericVisitorWithDefaults;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Type.ArrayType;
import com.sun.tools.javac.code.Type.ClassType;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic.Kind;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.expression.ArrayAccess;
import org.checkerframework.dataflow.expression.ArrayCreation;
import org.checkerframework.dataflow.expression.BinaryOperation;
import org.checkerframework.dataflow.expression.ClassName;
import org.checkerframework.dataflow.expression.FieldAccess;
import org.checkerframework.dataflow.expression.FormalParameter;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.dataflow.expression.LocalVariable;
import org.checkerframework.dataflow.expression.MethodCall;
import org.checkerframework.dataflow.expression.ThisReference;
import org.checkerframework.dataflow.expression.UnaryOperation;
import org.checkerframework.dataflow.expression.ValueLiteral;
import org.checkerframework.framework.source.DiagMessage;
import org.checkerframework.framework.util.dependenttypes.DependentTypesError;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.Resolver;
import org.checkerframework.javacutil.TypesUtils;
import org.checkerframework.javacutil.trees.TreeBuilder;
import org.plumelib.util.CollectionsPlume;
import org.plumelib.util.StringsPlume;

/**
 * Helper methods to parse a string that represents a restricted Java expression.
 *
 * @checker_framework.manual #java-expressions-as-arguments Writing Java expressions as annotation
 *     arguments
 * @checker_framework.manual #dependent-types Annotations whose argument is a Java expression
 *     (dependent type annotations)
 */
public class JavaExpressionParseUtil {

  /** Regular expression for a formal parameter use. */
  protected static final String PARAMETER_REGEX = "#([1-9][0-9]*)";

  /**
   * Anchored pattern for a formal parameter use; matches a string that is exactly a formal
   * parameter use.
   */
  protected static final Pattern ANCHORED_PARAMETER_PATTERN =
      Pattern.compile("^" + PARAMETER_REGEX + "$");

  /**
   * Unanchored pattern for a formal parameter use; can be used to find all formal parameter uses.
   */
  protected static final Pattern UNANCHORED_PARAMETER_PATTERN = Pattern.compile(PARAMETER_REGEX);

  /**
   * Parsable replacement for formal parameter references. It is parsable because it is a Java
   * identifier.
   */
  private static final String PARAMETER_PREFIX = "_param_";

  /** The length of {@link #PARAMETER_PREFIX}. */
  private static final int PARAMETER_PREFIX_LENGTH = PARAMETER_PREFIX.length();

  /** A pattern that matches the start of a formal parameter in "#2" syntax. */
  private static Pattern FORMAL_PARAMETER = Pattern.compile("#(\\d)");

  /** The replacement for a formal parameter in "#2" syntax. */
  private static final String PARAMETER_REPLACEMENT = PARAMETER_PREFIX + "$1";

  /**
   * Parses a string to a {@link JavaExpression}.
   *
   * <p>For most uses, clients should call one of the static methods in {@link
   * StringToJavaExpression} rather than calling this method directly.
   *
   * @param expression the string expression to parse
   * @param enclosingType type of the class that encloses the JavaExpression
   * @param thisReference the JavaExpression to which to parse "this", or null if "this" should not
   *     appear in the expression
   * @param parameters list of JavaExpressions to which to parse formal parameter references such as
   *     "#2", or null if formal parameter references should not appear in the expression
   * @param localVarPath if non-null, the expression is parsed as if it were written at this
   *     location; affects only parsing of local variables
   * @param pathToCompilationUnit required to use the underlying Javac API
   * @param env the processing environment
   * @return {@code expression} as a {@code JavaExpression}
   * @throws JavaExpressionParseException if the string cannot be parsed
   */
  public static JavaExpression parse(
      String expression,
      TypeMirror enclosingType,
      @Nullable ThisReference thisReference,
      @Nullable List<FormalParameter> parameters,
      @Nullable TreePath localVarPath,
      TreePath pathToCompilationUnit,
      ProcessingEnvironment env)
      throws JavaExpressionParseException {

    String expressionWithParameterNames =
        StringsPlume.replaceAll(expression, FORMAL_PARAMETER, PARAMETER_REPLACEMENT);
    Expression expr;
    try {
      expr = JavaParserUtil.parseExpression(expressionWithParameterNames);
    } catch (ParseProblemException e) {
      String extra = ".";
      if (!e.getProblems().isEmpty()) {
        String message = e.getProblems().get(0).getMessage();
        int newLine = message.indexOf(System.lineSeparator());
        if (newLine != -1) {
          message = message.substring(0, newLine);
        }
        extra = ". Error message: " + message;
      }
      throw constructJavaExpressionParseError(expression, "the expression did not parse" + extra);
    }

    JavaExpression result =
        ExpressionToJavaExpressionVisitor.convert(
            expr,
            enclosingType,
            thisReference,
            parameters,
            localVarPath,
            pathToCompilationUnit,
            env);

    if (result instanceof ClassName && !expression.endsWith(".class")) {
      throw constructJavaExpressionParseError(
          expression,
          String.format(
              "a class name cannot terminate a Java expression string, where result=%s [%s]",
              result, result.getClass()));
    }
    return result;
  }

  /**
   * A visitor class that converts a JavaParser {@link Expression} to a {@link JavaExpression}. This
   * class does not viewpoint-adapt the expression.
   */
  private static class ExpressionToJavaExpressionVisitor
      extends GenericVisitorWithDefaults<JavaExpression, Void> {

    /**
     * The underlying javac API used to convert from Strings to Elements requires a tree path even
     * when the information could be deduced from elements alone. So use the path to the current
     * CompilationUnit.
     */
    private final TreePath pathToCompilationUnit;

    /** If non-null, the expression is parsed as if it were written at this location. */
    private final @Nullable TreePath localVarPath;

    /** The processing environment. */
    private final ProcessingEnvironment env;

    /** The resolver. Computed from the environment, but lazily initialized. */
    private @MonotonicNonNull Resolver resolver = null;

    /** The type utilities. */
    private final Types types;

    /** The java.lang.String type. */
    private final TypeMirror stringTypeMirror;

    /** The enclosing type. Used to look up unqualified method, field, and class names. */
    private final TypeMirror enclosingType;

    /**
     * The expression to use for "this". If {@code null}, a parse error will be thrown if "this"
     * appears in the expression.
     */
    private final @Nullable ThisReference thisReference;
    /**
     * For each formal parameter, the expression to which to parse it. For example, the second
     * (index 1) element of the list is what "#2" parses to. If this field is {@code null}, a parse
     * error will be thrown if "#2" appears in the expression.
     */
    private final @Nullable List<FormalParameter> parameters;

    /**
     * Create a new ExpressionToJavaExpressionVisitor.
     *
     * @param enclosingType type of the class that encloses the JavaExpression
     * @param thisReference JavaExpression to which to parse "this", or null if "this" should not
     *     appear in the expression
     * @param parameters list of JavaExpressions to which to parse a formal parameter reference such
     *     as "#2", or null if parameters should not appear in the expression
     * @param localVarPath if non-null, the expression is parsed as if it were written at this
     *     location
     * @param pathToCompilationUnit required to use the underlying Javac API
     * @param env the processing environment
     */
    private ExpressionToJavaExpressionVisitor(
        TypeMirror enclosingType,
        @Nullable ThisReference thisReference,
        @Nullable List<FormalParameter> parameters,
        @Nullable TreePath localVarPath,
        TreePath pathToCompilationUnit,
        ProcessingEnvironment env) {
      this.pathToCompilationUnit = pathToCompilationUnit;
      this.localVarPath = localVarPath;
      this.env = env;
      this.types = env.getTypeUtils();
      this.stringTypeMirror = env.getElementUtils().getTypeElement("java.lang.String").asType();
      this.enclosingType = enclosingType;
      this.thisReference = thisReference;
      this.parameters = parameters;
    }

    /**
     * Converts a JavaParser {@link Expression} to a {@link JavaExpression}.
     *
     * @param expr the JavaParser {@link Expression} to convert
     * @param enclosingType type of the class that encloses the JavaExpression
     * @param thisReference JavaExpression to which to parse "this", or null if "this" should not
     *     appear in the expression
     * @param parameters list of JavaExpressions to which to parse parameters, or null if parameters
     *     should not appear in the expression
     * @param localVarPath if non-null, the expression is parsed as if it were written at this
     *     location
     * @param pathToCompilationUnit required to use the underlying Javac API
     * @param env the processing environment
     * @return {@code expr} as a {@code JavaExpression}
     * @throws JavaExpressionParseException if {@code expr} cannot be converted to a {@code
     *     JavaExpression}
     */
    public static JavaExpression convert(
        Expression expr,
        TypeMirror enclosingType,
        @Nullable ThisReference thisReference,
        @Nullable List<FormalParameter> parameters,
        @Nullable TreePath localVarPath,
        TreePath pathToCompilationUnit,
        ProcessingEnvironment env)
        throws JavaExpressionParseException {
      try {
        return expr.accept(
            new ExpressionToJavaExpressionVisitor(
                enclosingType, thisReference, parameters, localVarPath, pathToCompilationUnit, env),
            null);
      } catch (ParseRuntimeException e) {
        // Convert unchecked to checked exception. Visitor methods can't throw checked
        // exceptions. They override the methods in the superclass, and a checked exception
        // would change the method signature.
        throw e.getCheckedException();
      }
    }

    /**
     * Initializes the {@code resolver} field if necessary. Does nothing on invocations after the
     * first.
     */
    private void setResolverField() {
      if (resolver == null) {
        resolver = new Resolver(env);
      }
    }

    /** If the expression is not supported, throw a {@link ParseRuntimeException} by default. */
    @Override
    public JavaExpression defaultAction(com.github.javaparser.ast.Node n, Void aVoid) {
      throw new ParseRuntimeException(
          constructJavaExpressionParseError(
              n.toString(), n.getClass() + " is not a supported expression"));
    }

    @Override
    public JavaExpression visit(NullLiteralExpr expr, Void aVoid) {
      return new ValueLiteral(types.getNullType(), (Object) null);
    }

    @Override
    public JavaExpression visit(IntegerLiteralExpr expr, Void aVoid) {
      return new ValueLiteral(types.getPrimitiveType(TypeKind.INT), expr.asNumber());
    }

    @Override
    public JavaExpression visit(LongLiteralExpr expr, Void aVoid) {
      return new ValueLiteral(types.getPrimitiveType(TypeKind.LONG), expr.asNumber());
    }

    @Override
    public JavaExpression visit(CharLiteralExpr expr, Void aVoid) {
      return new ValueLiteral(types.getPrimitiveType(TypeKind.CHAR), expr.asChar());
    }

    @Override
    public JavaExpression visit(DoubleLiteralExpr expr, Void aVoid) {
      return new ValueLiteral(types.getPrimitiveType(TypeKind.DOUBLE), expr.asDouble());
    }

    @Override
    public JavaExpression visit(StringLiteralExpr expr, Void aVoid) {
      return new ValueLiteral(stringTypeMirror, expr.asString());
    }

    @Override
    public JavaExpression visit(BooleanLiteralExpr expr, Void aVoid) {
      return new ValueLiteral(types.getPrimitiveType(TypeKind.BOOLEAN), expr.getValue());
    }

    @Override
    public JavaExpression visit(ThisExpr n, Void aVoid) {
      if (thisReference == null) {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError("this", "\"this\" isn't allowed here"));
      }
      return thisReference;
    }

    @Override
    public JavaExpression visit(SuperExpr n, Void aVoid) {
      // super literal
      TypeMirror superclass = TypesUtils.getSuperclass(enclosingType, types);
      if (superclass == null) {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError("super", enclosingType + " has no superclass"));
      }
      return new ThisReference(superclass);
    }

    // expr is an expression in parentheses.
    @Override
    public JavaExpression visit(EnclosedExpr expr, Void aVoid) {
      return expr.getInner().accept(this, null);
    }

    @Override
    public JavaExpression visit(ArrayAccessExpr expr, Void aVoid) {
      JavaExpression array = expr.getName().accept(this, null);
      TypeMirror arrayType = array.getType();
      if (arrayType.getKind() != TypeKind.ARRAY) {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError(
                expr.toString(),
                String.format(
                    "expected an array, found %s of type %s [%s]",
                    array, arrayType, arrayType.getKind())));
      }
      TypeMirror componentType = ((ArrayType) arrayType).getComponentType();

      JavaExpression index = expr.getIndex().accept(this, null);

      return new ArrayAccess(componentType, array, index);
    }

    // expr is an identifier with no dots in its name.
    @Override
    public JavaExpression visit(NameExpr expr, Void aVoid) {
      String s = expr.getNameAsString();
      setResolverField();

      // Formal parameter, using "#2" syntax.
      JavaExpression parameter = getParameterJavaExpression(s);
      if (parameter != null) {
        // A parameter is a local variable, but it can be referenced outside of local scope
        // (at the method scope) using the special #NN syntax.
        return parameter;
      }

      // Local variable or parameter.
      if (localVarPath != null) {
        // Attempt to match a local variable within the scope of the
        // given path before attempting to match a field.
        VariableElement varElem = resolver.findLocalVariableOrParameter(s, localVarPath);
        if (varElem != null) {
          return new LocalVariable(varElem);
        }
      }

      // Field access
      JavaExpression fieldAccessReceiver;
      if (thisReference != null) {
        fieldAccessReceiver = thisReference;
      } else {
        fieldAccessReceiver = new ClassName(enclosingType);
      }
      FieldAccess fieldAccess = getIdentifierAsFieldAccess(fieldAccessReceiver, s);
      if (fieldAccess != null) {
        return fieldAccess;
      }

      if (localVarPath != null) {
        Element classElem = resolver.findClass(s, localVarPath);
        TypeMirror classType = ElementUtils.getType(classElem);
        if (classType != null) {
          return new ClassName(classType);
        }
      }

      ClassName classType = getIdentifierAsUnqualifiedClassName(s);
      if (classType != null) {
        return classType;
      }

      // Err if a formal parameter name is used, instead of the "#2" syntax.
      if (parameters != null) {
        for (int i = 0; i < parameters.size(); i++) {
          Element varElt = parameters.get(i).getElement();
          if (varElt.getSimpleName().contentEquals(s)) {
            throw new ParseRuntimeException(
                constructJavaExpressionParseError(
                    s, String.format(DependentTypesError.FORMAL_PARAM_NAME_STRING, i + 1, s)));
          }
        }
      }

      throw new ParseRuntimeException(constructJavaExpressionParseError(s, "identifier not found"));
    }

    /**
     * If {@code s} a parameter expressed using the {@code #NN} syntax, then returns a
     * JavaExpression for the given parameter; that is, returns an element of {@code parameters}.
     * Otherwise, returns {@code null}.
     *
     * @param s a String that starts with PARAMETER_PREFIX
     * @return the JavaExpression for the given parameter or {@code null} if {@code s} is not a
     *     parameter
     */
    private @Nullable JavaExpression getParameterJavaExpression(String s) {
      if (!s.startsWith(PARAMETER_PREFIX)) {
        return null;
      }
      if (parameters == null) {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError(s, "no parameters found"));
      }
      int idx = Integer.parseInt(s.substring(PARAMETER_PREFIX_LENGTH));

      if (idx == 0) {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError(
                "#0", "Use \"this\" for the receiver or \"#1\" for the first formal parameter"));
      }
      if (idx > parameters.size()) {
        throw new ParseRuntimeException(
            new JavaExpressionParseException(
                "flowexpr.parse.index.too.big", Integer.toString(idx)));
      }
      return parameters.get(idx - 1);
    }

    /**
     * If {@code identifier} is the simple class name of any inner class of {@code type}, return the
     * {@link ClassName} for the inner class. If not, return null.
     *
     * @param type type to search for {@code identifier}
     * @param identifier possible simple class name
     * @return the {@code ClassName} for {@code identifier}, or null if it is not a simple class
     *     name
     */
    protected @Nullable ClassName getIdentifierAsInnerClassName(
        TypeMirror type, String identifier) {
      if (type.getKind() != TypeKind.DECLARED) {
        return null;
      }

      Element outerClass = ((DeclaredType) type).asElement();
      for (Element memberElement : outerClass.getEnclosedElements()) {
        if (!(memberElement.getKind().isClass() || memberElement.getKind().isInterface())) {
          continue;
        }
        if (memberElement.getSimpleName().contentEquals(identifier)) {
          return new ClassName(ElementUtils.getType(memberElement));
        }
      }
      return null;
    }

    /**
     * If {@code identifier} is a class name with that can be referenced using only its simple name
     * within {@code enclosingType}, return the {@link ClassName} for the class. If not, return
     * null.
     *
     * <p>{@code identifier} may be
     *
     * <ol>
     *   <li>the simple name of {@code type}.
     *   <li>the simple name of a class declared in {@code type} or in an enclosing type of {@code
     *       type}.
     *   <li>the simple name of a class in the java.lang package.
     *   <li>the simple name of a class in the unnamed package.
     * </ol>
     *
     * @param identifier possible class name
     * @return the {@code ClassName} for {@code identifier}, or null if it is not a class name
     */
    protected @Nullable ClassName getIdentifierAsUnqualifiedClassName(String identifier) {
      // Is identifier an inner class of enclosingType or of any enclosing class of enclosingType?
      TypeMirror searchType = enclosingType;
      while (searchType.getKind() == TypeKind.DECLARED) {
        DeclaredType searchDeclaredType = (DeclaredType) searchType;
        if (searchDeclaredType.asElement().getSimpleName().contentEquals(identifier)) {
          return new ClassName(searchType);
        }
        ClassName className = getIdentifierAsInnerClassName(searchType, identifier);
        if (className != null) {
          return className;
        }
        searchType = getTypeOfEnclosingClass(searchDeclaredType);
      }

      if (enclosingType.getKind() == TypeKind.DECLARED) {
        // Is identifier in the same package as this?
        PackageSymbol packageSymbol =
            (PackageSymbol)
                ElementUtils.enclosingPackage(((DeclaredType) enclosingType).asElement());
        ClassSymbol classSymbol =
            resolver.findClassInPackage(identifier, packageSymbol, pathToCompilationUnit);
        if (classSymbol != null) {
          return new ClassName(classSymbol.asType());
        }
      }
      // Is identifier a simple name for a class in java.lang?
      Symbol.PackageSymbol packageSymbol = resolver.findPackage("java.lang", pathToCompilationUnit);
      if (packageSymbol == null) {
        throw new BugInCF("Can't find java.lang package.");
      }
      ClassSymbol classSymbol =
          resolver.findClassInPackage(identifier, packageSymbol, pathToCompilationUnit);
      if (classSymbol != null) {
        return new ClassName(classSymbol.asType());
      }

      // Is identifier a class in the unnamed package?
      Element classElem = resolver.findClass(identifier, pathToCompilationUnit);
      if (classElem != null) {
        PackageElement pkg = ElementUtils.enclosingPackage(classElem);
        if (pkg != null && pkg.isUnnamed()) {
          TypeMirror classType = ElementUtils.getType(classElem);
          if (classType != null) {
            return new ClassName(classType);
          }
        }
      }

      return null;
    }

    /**
     * Return the {@link FieldAccess} expression for the field with name {@code identifier} accessed
     * via {@code receiverExpr}. If no such field exists, then {@code null} is returned.
     *
     * @param receiverExpr the receiver of the field access; the expression used to access the field
     * @param identifier possibly a field name
     * @return a field access, or null if {@code identifier} is not a field that can be accessed via
     *     {@code receiverExpr}
     */
    protected @Nullable FieldAccess getIdentifierAsFieldAccess(
        JavaExpression receiverExpr, String identifier) {
      // Find the field element.
      TypeMirror enclosingTypeOfField = receiverExpr.getType();
      VariableElement fieldElem;
      if (identifier.equals("length") && enclosingTypeOfField.getKind() == TypeKind.ARRAY) {
        fieldElem = resolver.findField(identifier, enclosingTypeOfField, pathToCompilationUnit);
        if (fieldElem == null) {
          throw new BugInCF("length field not found for type %s", enclosingTypeOfField);
        }
      } else {
        fieldElem = null;
        // Search for field in each enclosing class.
        while (enclosingTypeOfField.getKind() == TypeKind.DECLARED) {
          fieldElem = resolver.findField(identifier, enclosingTypeOfField, pathToCompilationUnit);
          if (fieldElem != null) {
            break;
          }
          enclosingTypeOfField = getTypeOfEnclosingClass((DeclaredType) enclosingTypeOfField);
        }
        if (fieldElem == null) {
          // field not found.
          return null;
        }
      }

      // Construct a FieldAccess expression.
      if (ElementUtils.isStatic(fieldElem)) {
        Element classElem = fieldElem.getEnclosingElement();
        JavaExpression staticClassReceiver = new ClassName(ElementUtils.getType(classElem));
        return new FieldAccess(staticClassReceiver, fieldElem);
      }

      // fieldElem is an instance field.

      if (receiverExpr instanceof ClassName) {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError(
                fieldElem.getSimpleName().toString(),
                "a non-static field cannot have a class name as a receiver."));
      }

      // There are two possibilities, captured by local variable fieldDeclaredInReceiverType:
      //  * true: it's an instance field declared in the type (or supertype) of receiverExpr.
      //  * false: it's an instance field declared in an enclosing type of receiverExpr.

      @SuppressWarnings("interning:not.interned") // Checking for exact object
      boolean fieldDeclaredInReceiverType = enclosingTypeOfField == receiverExpr.getType();
      if (fieldDeclaredInReceiverType) {
        TypeMirror fieldType = ElementUtils.getType(fieldElem);
        return new FieldAccess(receiverExpr, fieldType, fieldElem);
      } else {
        if (!(receiverExpr instanceof ThisReference)) {
          String msg =
              String.format(
                  "%s is declared in an outer type of the type of the receiver expression, %s.",
                  identifier, receiverExpr);
          throw new ParseRuntimeException(constructJavaExpressionParseError(identifier, msg));
        }
        TypeElement receiverTypeElement = TypesUtils.getTypeElement(receiverExpr.getType());
        if (receiverTypeElement == null || ElementUtils.isStatic(receiverTypeElement)) {
          String msg =
              String.format("%s is a non-static field declared in an outer type this.", identifier);
          throw new ParseRuntimeException(constructJavaExpressionParseError(identifier, msg));
        }
        JavaExpression locationOfField = new ThisReference(enclosingTypeOfField);
        return new FieldAccess(locationOfField, fieldElem);
      }
    }

    @Override
    public JavaExpression visit(MethodCallExpr expr, Void aVoid) {
      setResolverField();

      JavaExpression receiverExpr;
      if (expr.getScope().isPresent()) {
        receiverExpr = expr.getScope().get().accept(this, null);
        expr = expr.removeScope();
      } else if (thisReference != null) {
        receiverExpr = thisReference;
      } else {
        receiverExpr = new ClassName(enclosingType);
      }

      String methodName = expr.getNameAsString();

      // parse argument list
      List<JavaExpression> arguments =
          CollectionsPlume.mapList(argument -> argument.accept(this, null), expr.getArguments());

      ExecutableElement methodElement;
      try {
        methodElement =
            getMethodElement(
                methodName, receiverExpr.getType(), pathToCompilationUnit, arguments, resolver);
      } catch (JavaExpressionParseException e) {
        throw new ParseRuntimeException(e);
      }

      // Box any arguments that require it.
      for (int i = 0; i < arguments.size(); i++) {
        VariableElement parameter = methodElement.getParameters().get(i);
        TypeMirror parameterType = parameter.asType();
        JavaExpression argument = arguments.get(i);
        TypeMirror argumentType = argument.getType();
        // is boxing necessary?
        if (TypesUtils.isBoxedPrimitive(parameterType) && TypesUtils.isPrimitive(argumentType)) {
          // boxing is necessary
          MethodSymbol valueOfMethod = TreeBuilder.getValueOfMethod(env, parameterType);
          JavaExpression boxedParam =
              new MethodCall(
                  parameterType,
                  valueOfMethod,
                  new ClassName(parameterType),
                  Collections.singletonList(argument));
          arguments.set(i, boxedParam);
        }
      }

      // Build the MethodCall expression object.
      if (ElementUtils.isStatic(methodElement)) {
        Element classElem = methodElement.getEnclosingElement();
        JavaExpression staticClassReceiver = new ClassName(ElementUtils.getType(classElem));
        return new MethodCall(
            ElementUtils.getType(methodElement), methodElement, staticClassReceiver, arguments);
      } else {
        if (receiverExpr instanceof ClassName) {
          throw new ParseRuntimeException(
              constructJavaExpressionParseError(
                  expr.toString(),
                  "a non-static method call cannot have a class name as a receiver"));
        }
        TypeMirror methodType =
            TypesUtils.substituteMethodReturnType(methodElement, receiverExpr.getType(), env);
        return new MethodCall(methodType, methodElement, receiverExpr, arguments);
      }
    }

    /**
     * Returns the ExecutableElement for a method, or throws an exception.
     *
     * <p>(This method takes into account autoboxing.)
     *
     * @param methodName the method name
     * @param receiverType the receiver type
     * @param pathToCompilationUnit the path to the compilation unit
     * @param arguments the arguments
     * @param resolver the resolver
     * @return the ExecutableElement for a method, or throws an exception
     * @throws JavaExpressionParseException if the string cannot be parsed as a method name
     */
    private ExecutableElement getMethodElement(
        String methodName,
        TypeMirror receiverType,
        TreePath pathToCompilationUnit,
        List<JavaExpression> arguments,
        Resolver resolver)
        throws JavaExpressionParseException {

      List<TypeMirror> argumentTypes = CollectionsPlume.mapList(JavaExpression::getType, arguments);

      if (receiverType.getKind() == TypeKind.ARRAY) {
        ExecutableElement element =
            resolver.findMethod(methodName, receiverType, pathToCompilationUnit, argumentTypes);
        if (element == null) {
          throw constructJavaExpressionParseError(methodName, "no such method");
        }
        return element;
      }

      // Search for method in each enclosing class.
      while (receiverType.getKind() == TypeKind.DECLARED) {
        ExecutableElement element =
            resolver.findMethod(methodName, receiverType, pathToCompilationUnit, argumentTypes);
        if (element != null) {
          return element;
        }
        receiverType = getTypeOfEnclosingClass((DeclaredType) receiverType);
      }

      // Method not found.
      throw constructJavaExpressionParseError(methodName, "no such method");
    }

    // expr is a field access, a fully qualified class name, or a class name qualified with
    // another class name (e.g. {@code OuterClass.InnerClass})
    @Override
    public JavaExpression visit(FieldAccessExpr expr, Void aVoid) {
      setResolverField();

      Expression scope = expr.getScope();
      String name = expr.getNameAsString();

      // Check for fully qualified class name.
      Symbol.PackageSymbol packageSymbol =
          resolver.findPackage(scope.toString(), pathToCompilationUnit);
      if (packageSymbol != null) {
        ClassSymbol classSymbol =
            resolver.findClassInPackage(name, packageSymbol, pathToCompilationUnit);
        if (classSymbol != null) {
          return new ClassName(classSymbol.asType());
        }
        throw new ParseRuntimeException(
            constructJavaExpressionParseError(
                expr.toString(),
                "could not find class "
                    + expr.getNameAsString()
                    + " in package "
                    + scope.toString()));
      }

      JavaExpression receiver = scope.accept(this, null);

      // Check for field access expression.
      FieldAccess fieldAccess = getIdentifierAsFieldAccess(receiver, name);
      if (fieldAccess != null) {
        return fieldAccess;
      }

      // Check for inner class.
      ClassName classType = getIdentifierAsInnerClassName(receiver.getType(), name);
      if (classType != null) {
        return classType;
      }

      throw new ParseRuntimeException(
          constructJavaExpressionParseError(
              name, String.format("field or class %s not found in %s", name, receiver)));
    }

    // expr is a Class literal
    @Override
    public JavaExpression visit(ClassExpr expr, Void aVoid) {
      TypeMirror result = convertTypeToTypeMirror(expr.getType());
      if (result == null) {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError(
                expr.toString(), "it is an unparsable class literal"));
      }
      return new ClassName(result);
    }

    @Override
    public JavaExpression visit(ArrayCreationExpr expr, Void aVoid) {
      List<JavaExpression> dimensions =
          CollectionsPlume.mapList(
              (ArrayCreationLevel dimension) ->
                  dimension.getDimension().isPresent()
                      ? dimension.getDimension().get().accept(this, aVoid)
                      : null,
              expr.getLevels());

      List<JavaExpression> initializers;
      if (expr.getInitializer().isPresent()) {
        initializers =
            CollectionsPlume.mapList(
                (Expression initializer) -> initializer.accept(this, null),
                expr.getInitializer().get().getValues());
      } else {
        initializers = Collections.emptyList();
      }
      TypeMirror arrayType = convertTypeToTypeMirror(expr.getElementType());
      if (arrayType == null) {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError(
                expr.getElementType().asString(), "type not parsable"));
      }
      for (int i = 0; i < dimensions.size(); i++) {
        arrayType = TypesUtils.createArrayType(arrayType, env.getTypeUtils());
      }
      return new ArrayCreation(arrayType, dimensions, initializers);
    }

    @Override
    public JavaExpression visit(UnaryExpr expr, Void aVoid) {
      Tree.Kind treeKind = javaParserUnaryOperatorToTreeKind(expr.getOperator());
      JavaExpression operand = expr.getExpression().accept(this, null);
      // This eliminates + and performs constant-folding for -; it could also do so for other
      // operations.
      switch (treeKind) {
        case UNARY_PLUS:
          return operand;
        case UNARY_MINUS:
          if (operand instanceof ValueLiteral) {
            return ((ValueLiteral) operand).negate();
          }
          break;
        default:
          // Not optimization for this operand
          break;
      }
      return new UnaryOperation(operand.getType(), treeKind, operand);
    }

    /**
     * Convert a JavaParser unary operator to a TreeKind.
     *
     * @param op a JavaParser unary operator
     * @return a TreeKind for the unary operator
     */
    private Tree.Kind javaParserUnaryOperatorToTreeKind(UnaryExpr.Operator op) {
      switch (op) {
        case BITWISE_COMPLEMENT:
          return Tree.Kind.BITWISE_COMPLEMENT;
        case LOGICAL_COMPLEMENT:
          return Tree.Kind.LOGICAL_COMPLEMENT;
        case MINUS:
          return Tree.Kind.UNARY_MINUS;
        case PLUS:
          return Tree.Kind.UNARY_PLUS;
        case POSTFIX_DECREMENT:
          return Tree.Kind.POSTFIX_DECREMENT;
        case POSTFIX_INCREMENT:
          return Tree.Kind.POSTFIX_INCREMENT;
        case PREFIX_DECREMENT:
          return Tree.Kind.PREFIX_DECREMENT;
        case PREFIX_INCREMENT:
          return Tree.Kind.PREFIX_INCREMENT;
        default:
          throw new BugInCF("unhandled " + op);
      }
    }

    @Override
    public JavaExpression visit(BinaryExpr expr, Void aVoid) {
      JavaExpression leftJe = expr.getLeft().accept(this, null);
      JavaExpression rightJe = expr.getRight().accept(this, null);
      TypeMirror leftType = leftJe.getType();
      TypeMirror rightType = rightJe.getType();
      TypeMirror type;
      // isSubtype() first does the cheaper test isSameType(), so no need to do it here.
      if (types.isSubtype(leftType, rightType)) {
        type = rightType;
      } else if (types.isSubtype(rightType, leftType)) {
        type = leftType;
      } else if (expr.getOperator() == BinaryExpr.Operator.PLUS
          && (TypesUtils.isString(leftType) || TypesUtils.isString(rightType))) {
        type = stringTypeMirror;
      } else {
        throw new ParseRuntimeException(
            constructJavaExpressionParseError(
                expr.toString(),
                String.format("inconsistent types %s %s for %s", leftType, rightType, expr)));
      }
      return new BinaryOperation(
          type, javaParserBinaryOperatorToTreeKind(expr.getOperator()), leftJe, rightJe);
    }

    /**
     * Convert a JavaParser binary operator to a TreeKind.
     *
     * @param op a JavaParser binary operator
     * @return a TreeKind for the binary operator
     */
    private Tree.Kind javaParserBinaryOperatorToTreeKind(BinaryExpr.Operator op) {
      switch (op) {
        case AND:
          return Tree.Kind.CONDITIONAL_AND;
        case BINARY_AND:
          return Tree.Kind.AND;
        case BINARY_OR:
          return Tree.Kind.OR;
        case DIVIDE:
          return Tree.Kind.DIVIDE;
        case EQUALS:
          return Tree.Kind.EQUAL_TO;
        case GREATER:
          return Tree.Kind.GREATER_THAN;
        case GREATER_EQUALS:
          return Tree.Kind.GREATER_THAN_EQUAL;
        case LEFT_SHIFT:
          return Tree.Kind.LEFT_SHIFT;
        case LESS:
          return Tree.Kind.LESS_THAN;
        case LESS_EQUALS:
          return Tree.Kind.LESS_THAN_EQUAL;
        case MINUS:
          return Tree.Kind.MINUS;
        case MULTIPLY:
          return Tree.Kind.MULTIPLY;
        case NOT_EQUALS:
          return Tree.Kind.NOT_EQUAL_TO;
        case OR:
          return Tree.Kind.CONDITIONAL_OR;
        case PLUS:
          return Tree.Kind.PLUS;
        case REMAINDER:
          return Tree.Kind.REMAINDER;
        case SIGNED_RIGHT_SHIFT:
          return Tree.Kind.RIGHT_SHIFT;
        case UNSIGNED_RIGHT_SHIFT:
          return Tree.Kind.UNSIGNED_RIGHT_SHIFT;
        case XOR:
          return Tree.Kind.XOR;
        default:
          throw new Error("unhandled " + op);
      }
    }

    /**
     * Converts the JavaParser type to a TypeMirror. Returns null if {@code type} is not handled;
     * this method does not handle type variables, union types, or intersection types.
     *
     * @param type a JavaParser type
     * @return a TypeMirror corresponding to {@code type}, or null if {@code type} isn't handled
     */
    private @Nullable TypeMirror convertTypeToTypeMirror(Type type) {
      if (type.isClassOrInterfaceType()) {
        try {
          return JavaParserUtil.parseExpression(type.asString()).accept(this, null).getType();
        } catch (ParseProblemException e) {
          return null;
        }
      } else if (type.isPrimitiveType()) {
        switch (type.asPrimitiveType().getType()) {
          case BOOLEAN:
            return types.getPrimitiveType(TypeKind.BOOLEAN);
          case BYTE:
            return types.getPrimitiveType(TypeKind.BYTE);
          case SHORT:
            return types.getPrimitiveType(TypeKind.SHORT);
          case INT:
            return types.getPrimitiveType(TypeKind.INT);
          case CHAR:
            return types.getPrimitiveType(TypeKind.CHAR);
          case FLOAT:
            return types.getPrimitiveType(TypeKind.FLOAT);
          case LONG:
            return types.getPrimitiveType(TypeKind.LONG);
          case DOUBLE:
            return types.getPrimitiveType(TypeKind.DOUBLE);
        }
      } else if (type.isVoidType()) {
        return types.getNoType(TypeKind.VOID);
      } else if (type.isArrayType()) {
        TypeMirror componentType = convertTypeToTypeMirror(type.asArrayType().getComponentType());
        if (componentType == null) {
          return null;
        }
        return types.getArrayType(componentType);
      }
      return null;
    }
  }

  /**
   * If {@code s} is exactly a formal parameter, return its 1-based index. Returns -1 otherwise.
   *
   * @param s a Java expression
   * @return the 1-based index of the formal parameter that {@code s} represents, or -1
   */
  public static int parameterIndex(String s) {
    Matcher matcher = ANCHORED_PARAMETER_PATTERN.matcher(s);
    if (matcher.find()) {
      return Integer.parseInt(matcher.group(1));
    }
    return -1;
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Contexts
  ///

  /**
   * Returns the type of the innermost enclosing class. Returns Type.noType if the type is a
   * top-level class.
   *
   * <p>If the innermost enclosing class is static, this method returns the type of that class. By
   * contrast, {@link DeclaredType#getEnclosingType()} returns the type of the innermost enclosing
   * class that is not static.
   *
   * @param type a DeclaredType
   * @return the type of the innermost enclosing class or Type.noType
   */
  private static TypeMirror getTypeOfEnclosingClass(DeclaredType type) {
    if (type instanceof ClassType) {
      // enclClass() needs to be called on tsym.owner, because tsym.enclClass() == tsym.
      Symbol sym = ((ClassType) type).tsym.owner;
      if (sym == null) {
        return com.sun.tools.javac.code.Type.noType;
      }

      ClassSymbol cs = sym.enclClass();
      if (cs == null) {
        return com.sun.tools.javac.code.Type.noType;
      }

      return cs.asType();
    } else {
      return type.getEnclosingType();
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Exceptions
  ///

  /**
   * An exception that indicates a parse error. Call {@link #getDiagMessage} to obtain a {@link
   * DiagMessage} that can be used for error reporting.
   */
  public static class JavaExpressionParseException extends Exception {
    private static final long serialVersionUID = 2L;
    /** The error message key. */
    private @CompilerMessageKey String errorKey;
    /** The arguments to the error message key. */
    public final Object[] args;

    /**
     * Create a new JavaExpressionParseException.
     *
     * @param errorKey the error message key
     * @param args the arguments to the error message key
     */
    public JavaExpressionParseException(@CompilerMessageKey String errorKey, Object... args) {
      this(null, errorKey, args);
    }

    /**
     * Create a new JavaExpressionParseException.
     *
     * @param cause cause
     * @param errorKey the error message key
     * @param args the arguments to the error message key
     */
    public JavaExpressionParseException(
        @Nullable Throwable cause, @CompilerMessageKey String errorKey, Object... args) {
      super(cause);
      this.errorKey = errorKey;
      this.args = args;
    }

    @Override
    public String getMessage() {
      return errorKey + " " + Arrays.toString(args);
    }

    /**
     * Return a DiagMessage that can be used for error reporting.
     *
     * @return a DiagMessage that can be used for error reporting
     */
    public DiagMessage getDiagMessage() {
      return new DiagMessage(Kind.ERROR, errorKey, args);
    }

    public boolean isFlowParseError() {
      return errorKey.endsWith("flowexpr.parse.error");
    }
  }

  /**
   * Returns a {@link JavaExpressionParseException} with error key "flowexpr.parse.error" for the
   * expression {@code expr} with explanation {@code explanation}.
   *
   * @param expr the string that could not be parsed
   * @param explanation an explanation of the parse failure
   * @return a {@link JavaExpressionParseException} for the expression {@code expr} with explanation
   *     {@code explanation}.
   */
  private static JavaExpressionParseException constructJavaExpressionParseError(
      String expr, String explanation) {
    if (expr == null) {
      throw new BugInCF("Must have an expression.");
    }
    if (explanation == null) {
      throw new BugInCF("Must have an explanation.");
    }
    return new JavaExpressionParseException(
        (Throwable) null, "flowexpr.parse.error", "Invalid '" + expr + "' because " + explanation);
  }

  /**
   * The unchecked exception equivalent of checked exception {@link JavaExpressionParseException}.
   */
  private static class ParseRuntimeException extends RuntimeException {
    private static final long serialVersionUID = 2L;
    private final JavaExpressionParseException exception;

    private ParseRuntimeException(JavaExpressionParseException exception) {
      this.exception = exception;
    }

    private JavaExpressionParseException getCheckedException() {
      return exception;
    }
  }
}
