package org.checkerframework.framework.util.dependenttypes;

import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.expression.FormalParameter;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.dataflow.expression.JavaExpressionConverter;
import org.checkerframework.dataflow.expression.LocalVariable;
import org.checkerframework.dataflow.expression.Unknown;
import org.checkerframework.framework.source.SourceChecker;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeParameterBounds;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.framework.type.visitor.AnnotatedTypeScanner;
import org.checkerframework.framework.type.visitor.DoubleAnnotatedTypeScanner;
import org.checkerframework.framework.type.visitor.SimpleAnnotatedTypeScanner;
import org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException;
import org.checkerframework.framework.util.StringToJavaExpression;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.CollectionsPlume;

/**
 * A class that helps checkers use qualifiers that are represented by annotations with Java
 * expression strings. This class performs the following main functions:
 *
 * <ol>
 *   <li>Converts the expression strings in an {@link AnnotationMirror} {@code am}, by creating a
 *       new annotation whose Java expression elements are the result of the conversion. See {@link
 *       #convertAnnotationMirror(StringToJavaExpression, AnnotationMirror)}. Subclasses can
 *       specialize this process by overriding methods in this class. Methods in this class always
 *       standardize Java expressions and may additionally viewpoint-adapt or delocalize
 *       expressions. Below is an explanation of each kind of conversion.
 *       <ul>
 *         <li>Standardization: the expressions in the annotations are converted such that two
 *             expression strings that are equivalent are made to be equal. For example, an instance
 *             field f may appear in an expression string as "f" or "this.f"; this class
 *             standardizes both strings to "this.f". All dependent type annotations must be
 *             standardized so that the implementation of {@link
 *             org.checkerframework.framework.type.QualifierHierarchy#isSubtype(AnnotationMirror,
 *             AnnotationMirror)} can assume that two expressions are equivalent if their string
 *             representations are {@code equals()}.
 *         <li>Viewpoint-adaption: converts an expression to some use site. For example, in method
 *             bodies, formal parameter references such as "#2" are converted to the name of the
 *             formal parameter. Another example, is at method call site, "this" is converted to the
 *             receiver of the method invocation.
 *         <li>Delocalization: removes all expressions with references to local variables that are
 *             not parameters and changes parameters to the "#1" syntax.
 *       </ul>
 *   <li>If any of the conversions above results in an invalid expression, this class changes
 *       invalid expression strings to an error string that includes the reason why the expression
 *       is invalid. For example, {@code @KeyFor("m")} would be changed to {@code @KeyFor("[error
 *       for expression: m error: m: identifier not found]")} if m is not a valid identifier. This
 *       allows subtyping checks to assume that if two strings are equal and not errors, they
 *       reference the same valid Java expression.
 *   <li>Checks annotated types for error strings that have been added by this class and issues an
 *       error if any are found.
 * </ol>
 *
 * <p>Steps 2 and 3 are separated so that an error is issued only once per invalid expression string
 * rather than every time the expression string is parsed. (The expression string is parsed multiple
 * times because annotated types are created multiple times.)
 */
public class DependentTypesHelper {

  /** AnnotatedTypeFactory */
  protected final AnnotatedTypeFactory factory;

  /**
   * Maps from an annotation name, the fully-qualified name of its class, to its elements that are
   * Java expressions.
   */
  private final Map<String, List<ExecutableElement>> annoToElements;

  /** This scans an annotated type and returns a list of {@link DependentTypesError}. */
  private final ExpressionErrorCollector expressionErrorCollector = new ExpressionErrorCollector();

  /**
   * A scanner that applies a function to each {@link AnnotationMirror} and replaces it in the given
   * {@code AnnotatedTypeMirror}. (This side-effects the {@code AnnotatedTypeMirror}.)
   */
  private final AnnotatedTypeReplacer annotatedTypeReplacer = new AnnotatedTypeReplacer();

  /**
   * Copies annotations that might have been viewpoint adapted from the visited type (the first
   * formal parameter of {@code ViewpointAdaptedCopier#visit}) to the second formal parameter.
   */
  private final ViewpointAdaptedCopier viewpointAdaptedCopier = new ViewpointAdaptedCopier();

  /** The type mirror for java.lang.Object. */
  protected final TypeMirror objectTM;

  /**
   * Creates a {@code DependentTypesHelper}.
   *
   * @param factory annotated type factory
   */
  public DependentTypesHelper(AnnotatedTypeFactory factory) {
    this.factory = factory;

    this.annoToElements = new HashMap<>();
    for (Class<? extends Annotation> expressionAnno : factory.getSupportedTypeQualifiers()) {
      List<ExecutableElement> elementList =
          getExpressionElements(expressionAnno, factory.getProcessingEnv());
      if (!elementList.isEmpty()) {
        annoToElements.put(expressionAnno.getCanonicalName(), elementList);
      }
    }

    this.objectTM =
        TypesUtils.typeFromClass(Object.class, factory.types, factory.getElementUtils());
  }

  /**
   * Returns true if any qualifier in the type system is a dependent type annotation.
   *
   * @return true if any qualifier in the type system is a dependent type annotation
   */
  public boolean hasDependentAnnotations() {
    return !annoToElements.isEmpty();
  }

  /**
   * Returns a list of the elements in the annotation class that should be interpreted as Java
   * expressions, namely those annotated with {@code @}{@link JavaExpression}.
   *
   * @param clazz annotation class
   * @param env processing environment for getting the ExecutableElement
   * @return a list of the elements in the annotation class that should be interpreted as Java
   *     expressions
   */
  private static List<ExecutableElement> getExpressionElements(
      Class<? extends Annotation> clazz, ProcessingEnvironment env) {
    Method[] methods = clazz.getMethods();
    if (methods == null) {
      return Collections.emptyList();
    }
    List<ExecutableElement> elements = new ArrayList<>();
    for (Method method : methods) {
      org.checkerframework.framework.qual.JavaExpression javaExpressionAnno =
          method.getAnnotation(org.checkerframework.framework.qual.JavaExpression.class);
      if (javaExpressionAnno != null) {
        elements.add(TreeUtils.getMethod(clazz, method.getName(), method.getParameterCount(), env));
      }
    }
    return elements;
  }

  /**
   * Returns the elements of the annotation that are Java expressions.
   *
   * @param am AnnotationMirror
   * @return the elements of the annotation that are Java expressions
   */
  private List<ExecutableElement> getListOfExpressionElements(AnnotationMirror am) {
    return annoToElements.getOrDefault(AnnotationUtils.annotationName(am), Collections.emptyList());
  }

  /**
   * Creates a TreeAnnotator that viewpoint-adapts dependent type annotations.
   *
   * @return a new TreeAnnotator that viewpoint-adapts dependent type annotations
   */
  public TreeAnnotator createDependentTypesTreeAnnotator() {
    assert hasDependentAnnotations();
    return new DependentTypesTreeAnnotator(factory, this);
  }

  ///
  /// Methods that convert annotations
  ///

  /** If true, log information about where lambdas are created. */
  private static boolean debugStringToJavaExpression = false;

  /**
   * Viewpoint-adapts the dependent type annotations on the bounds of the type parameters of the
   * declaration of {@code typeUse} to {@code typeUse}.
   *
   * @param bounds annotated types of the bounds of the type parameters; its elements are
   *     side-effected by this method (but the list itself is not side-effected)
   * @param typeUse a use of a type with type parameter bounds {@code bounds}
   */
  public void atParameterizedTypeUse(
      List<AnnotatedTypeParameterBounds> bounds, TypeElement typeUse) {
    if (!hasDependentAnnotations()) {
      return;
    }

    StringToJavaExpression stringToJavaExpr =
        stringExpr -> StringToJavaExpression.atTypeDecl(stringExpr, typeUse, factory.getChecker());
    if (debugStringToJavaExpression) {
      System.out.printf(
          "atParameterizedTypeUse(%s, %s) created %s%n", bounds, typeUse, stringToJavaExpr);
    }
    for (AnnotatedTypeParameterBounds bound : bounds) {
      convertAnnotatedTypeMirror(stringToJavaExpr, bound.getUpperBound());
      convertAnnotatedTypeMirror(stringToJavaExpr, bound.getLowerBound());
    }
  }

  /**
   * Viewpoint-adapts the dependent type annotations in the methodType to the methodInvocationTree.
   *
   * <p>{@code methodType} has been viewpoint-adapted to the call site, except for any dependent
   * type annotations. This method viewpoint-adapts the dependent type annotations.
   *
   * @param methodType type of the method invocation; is side-effected by this method
   * @param methodInvocationTree use of the method
   */
  public void atMethodInvocation(
      AnnotatedExecutableType methodType, MethodInvocationTree methodInvocationTree) {
    if (!hasDependentAnnotations()) {
      return;
    }
    atInvocation(methodType, methodInvocationTree);
  }

  /**
   * Viewpoint-adapts the dependent type annotations in the constructorType to the newClassTree.
   *
   * <p>{@code constructorType} has been viewpoint-adapted to the call site, except for any
   * dependent type annotations. This method viewpoint-adapts the dependent type annotations.
   *
   * @param constructorType type of the constructor invocation; is side-effected by this method
   * @param newClassTree invocation of the constructor
   */
  public void atConstructorInvocation(
      AnnotatedExecutableType constructorType, NewClassTree newClassTree) {
    if (!hasDependentAnnotations()) {
      return;
    }
    atInvocation(constructorType, newClassTree);
  }

  /**
   * Viewpoint-adapts a method or constructor invocation.
   *
   * <p>{@code methodType} has been viewpoint-adapted to the call site, except for any dependent
   * type annotations. (For example, type variables have been substituted and polymorphic qualifiers
   * have been resolved.) This method viewpoint-adapts the dependent type annotations.
   *
   * @param methodType type of the method or constructor invocation; is side-effected by this method
   * @param tree invocation of the method or constructor
   */
  private void atInvocation(AnnotatedExecutableType methodType, ExpressionTree tree) {
    assert hasDependentAnnotations();
    Element methodElt = TreeUtils.elementFromUse(tree);
    // Because methodType is the type post type variable substitution, it has annotations from
    // both the method declaration and the type arguments at the use of the method. Annotations
    // from type arguments must not be viewpoint-adapted to the call site. For example:
    //   Map<String, String> map = ...;
    //   List<@KeyFor("this.map") String> list = ...;
    //   list.get(0)
    //
    // methodType is @KeyFor("this.map") String get(int)
    // "this.map" must not be viewpoint-adapted to the invocation because it is not from
    // the method declaration, but added during type variable substitution.
    //
    // So this implementation gets the declared type of the method, declaredMethodType,
    // viewpoint-adapts all dependent type annotations in declaredMethodType to the call site,
    // and then copies the viewpoint-adapted annotations from methodType except for types that
    // are replaced by type variable substitution. (Those annotations are viewpoint-adapted
    // before type variable substitution.)

    // The annotations on `declaredMethodType` will be copied to `methodType`.
    AnnotatedExecutableType declaredMethodType =
        (AnnotatedExecutableType) factory.getAnnotatedType(methodElt);
    if (!hasDependentType(declaredMethodType)) {
      return;
    }

    StringToJavaExpression stringToJavaExpr;
    if (tree instanceof MethodInvocationTree) {
      stringToJavaExpr =
          stringExpr ->
              StringToJavaExpression.atMethodInvocation(
                  stringExpr, (MethodInvocationTree) tree, factory.getChecker());
      if (debugStringToJavaExpression) {
        System.out.printf(
            "atInvocation(%s, %s) 1 created %s%n",
            methodType, TreeUtils.toStringTruncated(tree, 65), stringToJavaExpr);
      }
    } else if (tree instanceof NewClassTree) {
      stringToJavaExpr =
          stringExpr ->
              StringToJavaExpression.atConstructorInvocation(
                  stringExpr, (NewClassTree) tree, factory.getChecker());
      if (debugStringToJavaExpression) {
        System.out.printf(
            "atInvocation(%s, %s) 2 created %s%n",
            methodType, TreeUtils.toStringTruncated(tree, 65), stringToJavaExpr);
      }
    } else {
      throw new BugInCF("Unexpected tree: %s kind: %s", tree, tree.getKind());
    }
    convertAnnotatedTypeMirror(stringToJavaExpr, declaredMethodType);
    this.viewpointAdaptedCopier.visit(declaredMethodType, methodType);
  }

  /**
   * Viewpoint-adapts the Java expressions in annotations written on a field declaration to the use
   * at {@code fieldAccess}.
   *
   * @param type its type; is side-effected by this method
   * @param fieldAccess a field access
   */
  public void atFieldAccess(AnnotatedTypeMirror type, MemberSelectTree fieldAccess) {
    if (!hasDependentType(type)) {
      return;
    }

    StringToJavaExpression stringToJavaExpr =
        stringExpr ->
            StringToJavaExpression.atFieldAccess(stringExpr, fieldAccess, factory.getChecker());
    if (debugStringToJavaExpression) {
      System.out.printf(
          "atFieldAccess(%s, %s) created %s%n",
          type, TreeUtils.toStringTruncated(fieldAccess, 65), stringToJavaExpr);
    }
    convertAnnotatedTypeMirror(stringToJavaExpr, type);
  }

  /**
   * Viewpoint-adapts the Java expressions in annotations written on the signature of the method
   * declaration (for example, a return type) to the body of the method. This means the parameter
   * syntax, e.g. "#2", is converted to the names of the parameter.
   *
   * @param atm a type at the method signature; is side-effected by this method
   * @param methodDeclTree a method declaration
   */
  public void atMethodBody(AnnotatedTypeMirror atm, MethodTree methodDeclTree) {
    if (!hasDependentType(atm)) {
      return;
    }

    StringToJavaExpression stringToJavaExpr =
        stringExpr ->
            StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, factory.getChecker());
    if (debugStringToJavaExpression) {
      System.out.printf(
          "atMethodBody(%s, %s) 1 created %s%n",
          atm, TreeUtils.toStringTruncated(methodDeclTree, 65), stringToJavaExpr);
    }
    convertAnnotatedTypeMirror(stringToJavaExpr, atm);
  }

  /**
   * Standardizes the Java expressions in annotations to a type declaration.
   *
   * @param type the type of the type declaration; is side-effected by this method
   * @param typeElt the element of the type declaration
   */
  public void atTypeDecl(AnnotatedTypeMirror type, TypeElement typeElt) {
    if (!hasDependentType(type)) {
      return;
    }

    StringToJavaExpression stringToJavaExpr =
        stringExpr -> StringToJavaExpression.atTypeDecl(stringExpr, typeElt, factory.getChecker());
    if (debugStringToJavaExpression) {
      System.out.printf("atTypeDecl(%s, %s) created %s%n", type, typeElt, stringToJavaExpr);
    }
    convertAnnotatedTypeMirror(stringToJavaExpr, type);
  }

  /** A set containing {@link Tree.Kind#METHOD} and {@link Tree.Kind#LAMBDA_EXPRESSION}. */
  private static final Set<Tree.Kind> METHOD_OR_LAMBDA =
      EnumSet.of(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION);

  /**
   * Standardize the Java expressions in annotations in a variable declaration. Converts the
   * parameter syntax, e.g "#1", to the parameter name.
   *
   * @param type the type of the variable declaration; is side-effected by this method
   * @param declarationTree the variable declaration
   * @param variableElt the element of the variable declaration
   */
  public void atVariableDeclaration(
      AnnotatedTypeMirror type, Tree declarationTree, VariableElement variableElt) {
    if (!hasDependentType(type)) {
      return;
    }

    TreePath pathToVariableDecl = factory.getPath(declarationTree);
    if (pathToVariableDecl == null) {
      // If this is a synthetic created by dataflow, the path will be null.
      return;
    }
    switch (variableElt.getKind()) {
      case PARAMETER:
        TreePath pathTillEnclTree =
            TreePathUtil.pathTillOfKind(pathToVariableDecl, METHOD_OR_LAMBDA);
        if (pathTillEnclTree == null) {
          throw new BugInCF("no enclosing method or lambda found for " + variableElt);
        }
        Tree enclTree = pathTillEnclTree.getLeaf();

        if (enclTree.getKind() == Kind.METHOD) {
          MethodTree methodDeclTree = (MethodTree) enclTree;
          StringToJavaExpression stringToJavaExpr =
              stringExpr ->
                  StringToJavaExpression.atMethodBody(
                      stringExpr, methodDeclTree, factory.getChecker());
          if (debugStringToJavaExpression) {
            System.out.printf(
                "atVariableDeclaration(%s, %s, %s) 1 created %s%n",
                type,
                TreeUtils.toStringTruncated(declarationTree, 65),
                variableElt,
                stringToJavaExpr);
          }
          convertAnnotatedTypeMirror(stringToJavaExpr, type);
        } else {
          // Lambdas can use local variables defined in the enclosing method, so allow
          // identifiers to be locals in scope at the location of the lambda.
          StringToJavaExpression stringToJavaExpr =
              stringExpr ->
                  StringToJavaExpression.atLambdaParameter(
                      stringExpr,
                      (LambdaExpressionTree) enclTree,
                      pathToVariableDecl.getParentPath(),
                      factory.getChecker());
          if (debugStringToJavaExpression) {
            System.out.printf(
                "atVariableDeclaration(%s, %s, %s) 2 created %s%n",
                type,
                TreeUtils.toStringTruncated(declarationTree, 65),
                variableElt,
                stringToJavaExpr);
          }
          convertAnnotatedTypeMirror(stringToJavaExpr, type);
        }
        break;

      case LOCAL_VARIABLE:
      case RESOURCE_VARIABLE:
      case EXCEPTION_PARAMETER:
        StringToJavaExpression stringToJavaExprVar =
            stringExpr ->
                StringToJavaExpression.atPath(stringExpr, pathToVariableDecl, factory.getChecker());
        if (debugStringToJavaExpression) {
          System.out.printf(
              "atVariableDeclaration(%s, %s, %s) 3 created %s%n",
              type,
              TreeUtils.toStringTruncated(declarationTree, 65),
              variableElt,
              stringToJavaExprVar);
        }
        convertAnnotatedTypeMirror(stringToJavaExprVar, type);
        break;

      case FIELD:
      case ENUM_CONSTANT:
        StringToJavaExpression stringToJavaExprField =
            stringExpr ->
                StringToJavaExpression.atFieldDecl(stringExpr, variableElt, factory.getChecker());
        if (debugStringToJavaExpression) {
          System.out.printf(
              "atVariableDeclaration(%s, %s, %s) 4 created %s%n",
              type,
              TreeUtils.toStringTruncated(declarationTree, 65),
              variableElt,
              stringToJavaExprField);
        }
        convertAnnotatedTypeMirror(stringToJavaExprField, type);
        break;

      default:
        throw new BugInCF(
            "unexpected element kind " + variableElt.getKind() + " for " + variableElt);
    }
  }

  /**
   * Standardize the Java expressions in annotations in written in the {@code expressionTree}. Also,
   * converts the parameter syntax, e.g. "#1", to the parameter name.
   *
   * <p>{@code expressionTree} must be an expressions which can contain explicitly written
   * annotations, namely a {@link NewClassTree}, {@link com.sun.source.tree.NewArrayTree}, or {@link
   * com.sun.source.tree.TypeCastTree}. For example, this method standardizes the {@code KeyFor}
   * annotation in {@code (@KeyFor("map") String) key }.
   *
   * @param annotatedType its type; is side-effected by this method
   * @param expressionTree a {@link NewClassTree}, {@link com.sun.source.tree.NewArrayTree}, or
   *     {@link com.sun.source.tree.TypeCastTree}
   */
  public void atExpression(AnnotatedTypeMirror annotatedType, ExpressionTree expressionTree) {
    if (!hasDependentType(annotatedType)) {
      return;
    }

    TreePath path = factory.getPath(expressionTree);
    if (path == null) {
      return;
    }
    StringToJavaExpression stringToJavaExpr =
        stringExpr -> StringToJavaExpression.atPath(stringExpr, path, factory.getChecker());
    if (debugStringToJavaExpression) {
      System.out.printf(
          "atExpression(%s, %s) created %s%n",
          annotatedType, TreeUtils.toStringTruncated(expressionTree, 65), stringToJavaExpr);
    }
    convertAnnotatedTypeMirror(stringToJavaExpr, annotatedType);
  }

  /**
   * Standardize the Java expressions in annotations in a type. Converts the parameter syntax, e.g.
   * "#2", to the parameter name.
   *
   * @param type the type to standardize; is side-effected by this method
   * @param elt the element whose type is {@code type}
   */
  public void atLocalVariable(AnnotatedTypeMirror type, Element elt) {
    if (!hasDependentType(type)) {
      return;
    }

    switch (elt.getKind()) {
      case PARAMETER:
      case LOCAL_VARIABLE:
      case RESOURCE_VARIABLE:
      case EXCEPTION_PARAMETER:
        Tree declarationTree = factory.declarationFromElement(elt);
        if (declarationTree == null) {
          if (elt.getKind() == ElementKind.PARAMETER) {
            // The tree might be null when
            // org.checkerframework.framework.flow.CFAbstractTransfer.getValueFromFactory() gets the
            // assignment context for a pseudo assignment of an argument to a method parameter.
            return;
          }
          throw new BugInCF(this.getClass() + ": tree not found");
        } else if (TreeUtils.typeOf(declarationTree) == null) {
          // org.checkerframework.framework.flow.CFAbstractTransfer.getValueFromFactory() gets the
          // assignment context for a pseudo assignment of an argument to a method parameter.
          return;
        }

        atVariableDeclaration(type, declarationTree, (VariableElement) elt);
        return;

      default:
        // It's not a local variable (it might be METHOD, CONSTRUCTOR, CLASS, or INTERFACE,
        // for example), so there is nothing to do.
        break;
    }
  }

  /** Thrown when a non-parameter local variable is found. */
  @SuppressWarnings("serial")
  private static class FoundLocalException extends RuntimeException {}

  /**
   * Viewpoint-adapt all dependent type annotations to the method declaration, {@code
   * methodDeclTree}. This method changes occurrences of formal parameter names to the "#2" syntax,
   * and it removes expressions that contain other local variables.
   *
   * <p>If a Java expression in {@code atm} references local variables (other than formal
   * parameters), the expression is removed from the annotation. This could result in dependent type
   * annotations with empty lists of expressions. If this is a problem, a subclass can override
   * {@link #buildAnnotation(AnnotationMirror, Map)} to do something besides creating an annotation
   * with a empty list.
   *
   * @param atm type to viewpoint-adapt; is side-effected by this method
   * @param methodDeclTree the method declaration to which the annotations are viewpoint-adapted
   */
  public void delocalize(AnnotatedTypeMirror atm, MethodTree methodDeclTree) {
    if (!hasDependentType(atm)) {
      return;
    }

    TreePath pathToMethodDecl = factory.getPath(methodDeclTree);
    ExecutableElement methodElement = TreeUtils.elementFromDeclaration(methodDeclTree);
    List<FormalParameter> parameters = JavaExpression.getFormalParameters(methodElement);
    List<JavaExpression> paramsAsLocals =
        JavaExpression.getParametersAsLocalVariables(methodElement);

    StringToJavaExpression stringToJavaExpr =
        expression -> {
          JavaExpression javaExpr;
          try {
            javaExpr =
                StringToJavaExpression.atPath(expression, pathToMethodDecl, factory.getChecker());
          } catch (JavaExpressionParseException ex) {
            return null;
          }
          JavaExpressionConverter jec =
              new JavaExpressionConverter() {
                @Override
                protected JavaExpression visitLocalVariable(
                    LocalVariable localVarExpr, Void unused) {
                  int index = paramsAsLocals.indexOf(localVarExpr);
                  if (index == -1) {
                    throw new FoundLocalException();
                  }
                  return parameters.get(index);
                }
              };
          try {
            return jec.convert(javaExpr);
          } catch (FoundLocalException ex) {
            return null;
          }
        };
    if (debugStringToJavaExpression) {
      System.out.printf(
          "delocalize(%s, %s) created %s%n",
          atm, TreeUtils.toStringTruncated(methodDeclTree, 65), stringToJavaExpr);
    }
    convertAnnotatedTypeMirror(stringToJavaExpr, atm);
  }

  /**
   * Calls {@link #convertAnnotationMirror(StringToJavaExpression, AnnotationMirror)} on each
   * annotation mirror on type with {@code stringToJavaExpr}. And replaces the annotation with the
   * one created by {@code convertAnnotationMirror}, if it's not null. If it is null, the original
   * annotation is used. See {@link #convertAnnotationMirror(StringToJavaExpression,
   * AnnotationMirror)} for more details.
   *
   * @param stringToJavaExpr function to convert a string to a {@link JavaExpression}
   * @param type the type that is side-effected by this method
   */
  protected void convertAnnotatedTypeMirror(
      StringToJavaExpression stringToJavaExpr, AnnotatedTypeMirror type) {
    this.annotatedTypeReplacer.visit(type, anno -> convertAnnotationMirror(stringToJavaExpr, anno));
  }

  /**
   * Given an annotation {@code anno}, this method builds a new annotation with the Java expressions
   * transformed according to {@code stringToJavaExpr}. If {@code anno} is not a dependent type
   * annotation, {@code null} is returned.
   *
   * <p>If {@code stringToJavaExpr} returns {@code null}, then that expression is removed from the
   * returned annotation.
   *
   * <p>Instead of overriding this method, subclasses can override the following methods to change
   * the behavior of this class:
   *
   * <ul>
   *   <li>{@link #shouldPassThroughExpression(String)}: to control which expressions are skipped.
   *       If this method returns true, then the expression string is not parsed and is included in
   *       the new annotation unchanged.
   *   <li>{@link #transform(JavaExpression)}: make changes to the JavaExpression produced by {@code
   *       stringToJavaExpr}.
   *   <li>{@link #buildAnnotation(AnnotationMirror, Map)}: to change the annotation returned by
   *       this method.
   * </ul>
   *
   * @param stringToJavaExpr function that converts strings to {@code JavaExpression}s
   * @param anno annotation mirror
   * @return an annotation created by applying {@code stringToJavaExpr} to all expression strings in
   *     {@code anno}, or null if there would be no effect
   */
  public @Nullable AnnotationMirror convertAnnotationMirror(
      StringToJavaExpression stringToJavaExpr, AnnotationMirror anno) {
    if (!isExpressionAnno(anno)) {
      return null;
    }

    Map<ExecutableElement, List<JavaExpression>> newElements = new HashMap<>();
    for (ExecutableElement element : getListOfExpressionElements(anno)) {
      List<String> expressionStrings =
          AnnotationUtils.getElementValueArray(
              anno, element, String.class, Collections.emptyList());
      List<JavaExpression> javaExprs = new ArrayList<>(expressionStrings.size());
      newElements.put(element, javaExprs);
      for (String expression : expressionStrings) {
        JavaExpression result;
        if (shouldPassThroughExpression(expression)) {
          result = new PassThroughExpression(objectTM, expression);
        } else {
          try {
            result = stringToJavaExpr.toJavaExpression(expression);
          } catch (JavaExpressionParseException e) {
            result = createError(expression, e);
          }
        }

        if (result != null) {
          result = transform(result);
          javaExprs.add(result);
        }
      }
    }
    return buildAnnotation(anno, newElements);
  }

  /**
   * This method is for subclasses to override to change JavaExpressions in some way before they are
   * inserted into new annotations. This method is called after parsing and viewpoint-adaptation
   * have occurred. {@code javaExpr} may be a {@link PassThroughExpression}.
   *
   * <p>If {@code null} is returned then the expression is not added to the new annotation.
   *
   * <p>The default implementation returns the argument, but subclasses may override it.
   *
   * @param javaExpr a JavaExpression
   * @return a transformed JavaExpression or {@code null} if no transformation exists
   */
  protected @Nullable JavaExpression transform(JavaExpression javaExpr) {
    return javaExpr;
  }

  /**
   * Whether or not {@code expression} should be passed to the new annotation unchanged. If this
   * method returns true, the {@code expression} is not parsed.
   *
   * <p>The default implementation returns true if the {@code expression} is an expression error
   * according to {@link DependentTypesError#isExpressionError(String)}. Subclasses may override
   * this method to add additional logic.
   *
   * @param expression an expression string in a dependent types annotation
   * @return whether or not {@code expression} should be passed through unchanged to the new
   *     annotation
   */
  protected boolean shouldPassThroughExpression(String expression) {
    return DependentTypesError.isExpressionError(expression);
  }

  /**
   * Create a new annotation of the same type as {@code originalAnno} using the provided {@code
   * elementMap}.
   *
   * @param originalAnno the annotation passed to {@link
   *     #convertAnnotationMirror(StringToJavaExpression, AnnotationMirror)} (this method is a
   *     helper method for {@link #convertAnnotationMirror(StringToJavaExpression,
   *     AnnotationMirror)})
   * @param elementMap a mapping from element of {@code originalAnno} to {@code JavaExpression}s
   * @return an annotation created from {@code elementMap}
   */
  protected AnnotationMirror buildAnnotation(
      AnnotationMirror originalAnno, Map<ExecutableElement, List<JavaExpression>> elementMap) {
    AnnotationBuilder builder =
        new AnnotationBuilder(
            factory.getProcessingEnv(), AnnotationUtils.annotationName(originalAnno));
    builder.copyElementValuesFromAnnotation(originalAnno, elementMap.keySet());
    for (Map.Entry<ExecutableElement, List<JavaExpression>> entry : elementMap.entrySet()) {
      List<String> strings = CollectionsPlume.mapList(JavaExpression::toString, entry.getValue());
      builder.setValue(entry.getKey(), strings);
    }
    return builder.build();
  }

  /**
   * A {@link JavaExpression} that does not represent a {@link JavaExpression}, but rather allows an
   * expression string to be converted to a JavaExpression and then to a string without parsing.
   */
  static class PassThroughExpression extends Unknown {
    /** Some string. */
    public final String string;

    /**
     * Creates a PassThroughExpression.
     *
     * @param type some type
     * @param string the string to convert to a JavaExpression
     */
    public PassThroughExpression(TypeMirror type, String string) {
      super(type);
      this.string = string;
    }

    @Override
    public String toString() {
      return string;
    }
  }

  /**
   * Creates a {@link JavaExpression} representing the exception thrown when parsing {@code
   * expression}.
   *
   * @param expression an expression that caused {@code e} when parsed
   * @param e the exception thrown when parsing {@code expression}
   * @return a java expression
   */
  protected PassThroughExpression createError(String expression, JavaExpressionParseException e) {
    return new PassThroughExpression(objectTM, new DependentTypesError(expression, e).toString());
  }

  /**
   * Creates a {@link JavaExpression} representing the error caused when parsing {@code expression}
   *
   * @param expression an expression that caused {@code error} when parsed
   * @param error the error message caused by {@code expression}
   * @return a java expression
   */
  protected PassThroughExpression createError(String expression, String error) {
    return new PassThroughExpression(
        objectTM, new DependentTypesError(expression, error).toString());
  }

  /**
   * Applies the passed function to each annotation in the given {@link AnnotatedTypeMirror}. If the
   * function returns a non-null annotation, then the original annotation is replaced with the
   * result. If the function returns null, the original annotation is retained.
   */
  private static class AnnotatedTypeReplacer
      extends AnnotatedTypeScanner<Void, Function<AnnotationMirror, AnnotationMirror>> {

    @Override
    public Void visitTypeVariable(
        AnnotatedTypeMirror.AnnotatedTypeVariable type,
        Function<AnnotationMirror, AnnotationMirror> func) {
      if (visitedNodes.containsKey(type)) {
        return visitedNodes.get(type);
      }
      visitedNodes.put(type, null);

      // If the type variable has a primary annotation, then it is viewpoint-adapted before this
      // method is called.  The viewpoint-adapted primary annotation was already copied to the upper
      // and lower bounds.  These annotations cannot be viewpoint-adapted again, so remove them,
      // viewpoint-adapt any other annotations in the bound, and then add them back.
      Set<AnnotationMirror> primarys = type.getAnnotations();
      type.getLowerBound().removeAnnotations(primarys);
      Void r = scan(type.getLowerBound(), func);
      type.getLowerBound().addAnnotations(primarys);
      visitedNodes.put(type, r);

      type.getUpperBound().removeAnnotations(primarys);
      r = scanAndReduce(type.getUpperBound(), func, r);
      type.getUpperBound().addAnnotations(primarys);
      visitedNodes.put(type, r);
      return r;
    }

    @Override
    protected Void scan(
        AnnotatedTypeMirror type, Function<AnnotationMirror, AnnotationMirror> func) {
      for (AnnotationMirror anno : AnnotationUtils.createAnnotationSet(type.getAnnotations())) {
        AnnotationMirror newAnno = func.apply(anno);
        if (newAnno != null) {
          // This code must remove and then add, rather than call `replace`, because a
          // type may have multiple annotations with the same class, but different
          // elements.  (This is a bug; see
          // https://github.com/typetools/checker-framework/issues/4451.)
          // AnnotatedTypeMirror#replace only removes one annotation that is in the same
          // hierarchy as the passed argument.
          type.removeAnnotation(anno);
          type.addAnnotation(newAnno);
        }
      }
      return super.scan(type, func);
    }
  }

  ///
  /// Methods that check and report errors
  ///

  /**
   * Reports an expression.unparsable error for each Java expression in the given type that is an
   * expression error string.
   *
   * @param atm annotated type to check for expression errors
   * @param errorTree the tree at which to report any found errors
   */
  public void checkTypeForErrorExpressions(AnnotatedTypeMirror atm, Tree errorTree) {
    if (!hasDependentAnnotations()) {
      return;
    }

    List<DependentTypesError> errors = expressionErrorCollector.visit(atm);
    if (errors.isEmpty()) {
      return;
    }

    if (errorTree.getKind() == Kind.VARIABLE) {
      ModifiersTree modifiers = ((VariableTree) errorTree).getModifiers();
      errorTree = ((VariableTree) errorTree).getType();
      for (AnnotationTree annoTree : modifiers.getAnnotations()) {
        String annoString = annoTree.toString();
        for (String annoName : annoToElements.keySet()) {
          // TODO: Simple string containment seems too simplistic.  At least check for a word
          // boundary.
          if (annoString.contains(annoName)) {
            errorTree = annoTree;
            break;
          }
        }
      }
    }
    reportErrors(errorTree, errors);
  }

  /**
   * Report the given errors as "expression.unparsable".
   *
   * @param errorTree where to report the errors
   * @param errors the errors to report
   */
  protected void reportErrors(Tree errorTree, List<DependentTypesError> errors) {
    SourceChecker checker = factory.getChecker();
    for (DependentTypesError dte : errors) {
      checker.reportError(errorTree, "expression.unparsable", dte.format());
    }
  }

  /**
   * Returns a list of {@link DependentTypesError}s for all the Java expression elements of the
   * annotation that are an error string as specified by DependentTypesError#isExpressionError.
   *
   * @param am an annotation
   * @return a list of {@link DependentTypesError}s for the error strings in the given annotation
   */
  private List<DependentTypesError> errorElements(AnnotationMirror am) {
    assert hasDependentAnnotations();

    List<DependentTypesError> errors = new ArrayList<>();

    for (ExecutableElement element : getListOfExpressionElements(am)) {
      // It's always an array, not a single value, because @JavaExpression may only be written
      // on an annotation element of type String[].
      List<String> value =
          AnnotationUtils.getElementValueArray(am, element, String.class, Collections.emptyList());
      for (String v : value) {
        if (DependentTypesError.isExpressionError(v)) {
          errors.add(DependentTypesError.unparse(v));
        }
      }
    }
    return errors;
  }

  /**
   * Reports a flowexpr.parse.error error for each Java expression in the given annotation that is
   * an expression error string.
   *
   * @param annotation annotation to check
   * @param errorTree location at which to issue errors
   */
  public void checkAnnotationForErrorExpressions(AnnotationMirror annotation, Tree errorTree) {
    if (!hasDependentAnnotations()) {
      return;
    }

    List<DependentTypesError> errors = errorElements(annotation);
    if (errors.isEmpty()) {
      return;
    }
    SourceChecker checker = factory.getChecker();
    for (DependentTypesError error : errors) {
      checker.reportError(errorTree, "flowexpr.parse.error", error);
    }
  }

  /**
   * Reports an expression.unparsable error for each Java expression in the given class declaration
   * AnnotatedTypeMirror that is an expression error string. Note that this reports errors in the
   * class declaration itself, not the body or extends/implements clauses.
   *
   * @param classTree class to check
   * @param type annotated type of the class
   */
  public void checkClassForErrorExpressions(ClassTree classTree, AnnotatedDeclaredType type) {
    if (!hasDependentAnnotations()) {
      return;
    }

    // TODO: check that invalid annotations in type variable bounds are properly
    // formatted. They are part of the type, but the output isn't nicely formatted.
    checkTypeForErrorExpressions(type, classTree);
  }

  /**
   * Reports an expression.unparsable error for each Java expression in the method declaration
   * AnnotatedTypeMirror that is an expression error string.
   *
   * @param methodDeclTree method to check
   * @param type annotated type of the method
   */
  public void checkMethodForErrorExpressions(
      MethodTree methodDeclTree, AnnotatedExecutableType type) {
    if (!hasDependentAnnotations()) {
      return;
    }

    // Parameters and receivers are checked by visitVariable
    // So only type parameters and return type need to be checked here.

    checkTypeVariablesForErrorExpressions(methodDeclTree, type);
    // Check return type
    if (type.getReturnType().getKind() != TypeKind.VOID) {
      AnnotatedTypeMirror returnType = factory.getMethodReturnType(methodDeclTree);
      Tree treeForError =
          TreeUtils.isConstructor(methodDeclTree) ? methodDeclTree : methodDeclTree.getReturnType();
      checkTypeForErrorExpressions(returnType, treeForError);
    }
  }

  /**
   * Reports an expression.unparsable error for each Java expression in the given type variables
   * that is an expression error string.
   *
   * @param node a method declaration
   * @param methodType annotated type of the method
   */
  private void checkTypeVariablesForErrorExpressions(
      MethodTree node, AnnotatedExecutableType methodType) {
    for (int i = 0; i < methodType.getTypeVariables().size(); i++) {
      AnnotatedTypeMirror atm = methodType.getTypeVariables().get(i);
      StringToJavaExpression stringToJavaExpr =
          stringExpr -> StringToJavaExpression.atMethodBody(stringExpr, node, factory.getChecker());
      if (debugStringToJavaExpression) {
        System.out.printf(
            "checkTypeVariablesForErrorExpressions(%s, %s) created %s%n",
            node, methodType, stringToJavaExpr);
      }
      convertAnnotatedTypeMirror(stringToJavaExpr, atm);
      checkTypeForErrorExpressions(atm, node.getTypeParameters().get(i));
    }
  }

  /**
   * Returns true if {@code am} is an expression annotation, that is, an annotation whose element is
   * a Java expression.
   *
   * @param am an annotation
   * @return true if {@code am} is an expression annotation
   */
  private boolean isExpressionAnno(AnnotationMirror am) {
    if (!hasDependentAnnotations()) {
      return false;
    }
    return annoToElements.containsKey(AnnotationUtils.annotationName(am));
  }

  /**
   * Checks all dependent type annotations in the given annotated type to see if the expression
   * string is an error string as specified by DependentTypesError#isExpressionError. If the
   * annotated type has any errors, then a non-empty list of {@link DependentTypesError} is
   * returned.
   */
  private class ExpressionErrorCollector
      extends SimpleAnnotatedTypeScanner<List<DependentTypesError>, Void> {

    /** Create ExpressionErrorCollector. */
    private ExpressionErrorCollector() {
      super(
          (AnnotatedTypeMirror type, Void aVoid) -> {
            List<DependentTypesError> errors = new ArrayList<>();
            for (AnnotationMirror am : type.getAnnotations()) {
              if (isExpressionAnno(am)) {
                errors.addAll(errorElements(am));
              }
            }
            return errors;
          },
          DependentTypesHelper::concatenate,
          Collections.emptyList());
    }
  }

  /**
   * Appends list2 to list1 in a new list. If either list is empty, returns the other. Thus, the
   * result may be aliased to one of the arguments and the client should only read, not write into,
   * the result.
   *
   * @param list1 a list
   * @param list2 a list
   * @return the lists, concatenated
   */
  private static List<DependentTypesError> concatenate(
      List<DependentTypesError> list1, List<DependentTypesError> list2) {
    if (list1.isEmpty()) {
      return list2;
    } else if (list2.isEmpty()) {
      return list1;
    }
    List<DependentTypesError> newList = new ArrayList<>(list1.size() + list2.size());
    newList.addAll(list1);
    newList.addAll(list2);
    return newList;
  }

  /**
   * The underlying type of the second parameter is the result of applying type variable
   * substitution to the visited type (the first parameter). This class copies annotations from the
   * visited type to the second formal parameter except for annotations on types that have been
   * substituted.
   */
  private class ViewpointAdaptedCopier extends DoubleAnnotatedTypeScanner<Void> {
    @Override
    protected Void scan(AnnotatedTypeMirror from, AnnotatedTypeMirror to) {
      if (from == null || to == null) {
        return null;
      }
      Set<AnnotationMirror> replacements = AnnotationUtils.createAnnotationSet();
      for (String vpa : annoToElements.keySet()) {
        AnnotationMirror anno = from.getAnnotation(vpa);
        if (anno != null) {
          // Only replace annotations that might have been changed.
          replacements.add(anno);
        }
      }
      to.replaceAnnotations(replacements);
      if (from.getKind() != to.getKind()) {
        // If the underlying types don't match, then this from has been substituted for a
        // from variable, so don't recur. The primary annotation was copied because
        // the from variable might have had a primary annotation at a use.
        // For example:
        // <T> void method(@KeyFor("a") T t) {...}
        // void use(@KeyFor("b") String s) {
        //      method(s);  // the from of the parameter should be @KeyFor("a") String
        // }
        return null;
      }
      return super.scan(from, to);
    }

    @Override
    protected Void defaultAction(AnnotatedTypeMirror type1, AnnotatedTypeMirror type2) {
      if (type1 == null || type2 == null) {
        return null;
      }
      if (type1.getKind() != type2.getKind()) {
        throw new BugInCF("Should be the same. type: %s p: %s ", type1, type2);
      }
      return null;
    }
  }

  /**
   * Returns true if {@code atm} has any dependent type annotations. If an annotated type does not
   * have a dependent type annotation, then no standardization or viewpoint adaption is performed.
   * (This check avoids calling time-intensive methods unless required.)
   *
   * @param atm a type
   * @return true if {@code atm} has any dependent type annotations
   */
  private boolean hasDependentType(AnnotatedTypeMirror atm) {
    if (atm == null) {
      return false;
    }
    // This is a test about the type system.
    if (!hasDependentAnnotations()) {
      return false;
    }
    // This is a test about this specific type.
    return hasDependentTypeScanner.visit(atm);
  }

  /** Returns true if the passed AnnotatedTypeMirror has any dependent type annotations. */
  private final AnnotatedTypeScanner<Boolean, Void> hasDependentTypeScanner =
      new SimpleAnnotatedTypeScanner<>(
          (type, __) -> {
            for (AnnotationMirror annotationMirror : type.getAnnotations()) {
              if (isExpressionAnno(annotationMirror)) {
                return true;
              }
            }
            return false;
          },
          Boolean::logicalOr,
          false);
}
