package org.checkerframework.framework.type;

// The imports from com.sun are all @jdk.Exported and therefore somewhat safe to use.
// Try to avoid using non-@jdk.Exported classes.

import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ConditionalExpressionTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree.JCNewClass;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
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.Name;
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.IntersectionType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import org.checkerframework.checker.interning.qual.FindDistinct;
import org.checkerframework.checker.interning.qual.InternedDistinct;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.CanonicalName;
import org.checkerframework.checker.signature.qual.FullyQualifiedName;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.basetype.BaseTypeVisitor;
import org.checkerframework.common.reflection.DefaultReflectionResolver;
import org.checkerframework.common.reflection.MethodValAnnotatedTypeFactory;
import org.checkerframework.common.reflection.MethodValChecker;
import org.checkerframework.common.reflection.ReflectionResolver;
import org.checkerframework.common.reflection.qual.MethodVal;
import org.checkerframework.common.wholeprograminference.WholeProgramInference;
import org.checkerframework.common.wholeprograminference.WholeProgramInferenceImplementation;
import org.checkerframework.common.wholeprograminference.WholeProgramInferenceJavaParserStorage;
import org.checkerframework.common.wholeprograminference.WholeProgramInferenceScenesStorage;
import org.checkerframework.dataflow.qual.SideEffectFree;
import org.checkerframework.framework.qual.AnnotatedFor;
import org.checkerframework.framework.qual.EnsuresQualifier;
import org.checkerframework.framework.qual.EnsuresQualifierIf;
import org.checkerframework.framework.qual.FieldInvariant;
import org.checkerframework.framework.qual.FromStubFile;
import org.checkerframework.framework.qual.HasQualifierParameter;
import org.checkerframework.framework.qual.InheritedAnnotation;
import org.checkerframework.framework.qual.NoQualifierParameter;
import org.checkerframework.framework.qual.RequiresQualifier;
import org.checkerframework.framework.source.SourceChecker;
import org.checkerframework.framework.stub.AnnotationFileElementTypes;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNullType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedPrimitiveType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.type.visitor.AnnotatedTypeCombiner;
import org.checkerframework.framework.type.visitor.SimpleAnnotatedTypeScanner;
import org.checkerframework.framework.util.AnnotatedTypes;
import org.checkerframework.framework.util.AnnotationFormatter;
import org.checkerframework.framework.util.CheckerMain;
import org.checkerframework.framework.util.DefaultAnnotationFormatter;
import org.checkerframework.framework.util.FieldInvariants;
import org.checkerframework.framework.util.TreePathCacher;
import org.checkerframework.framework.util.typeinference.DefaultTypeArgumentInference;
import org.checkerframework.framework.util.typeinference.TypeArgInferenceUtil;
import org.checkerframework.framework.util.typeinference.TypeArgumentInference;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.CollectionUtils;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypeKindUtils;
import org.checkerframework.javacutil.TypeSystemError;
import org.checkerframework.javacutil.TypesUtils;
import org.checkerframework.javacutil.UserError;
import org.checkerframework.javacutil.trees.DetachedVarSymbol;
import org.plumelib.util.CollectionsPlume;
import org.plumelib.util.StringsPlume;
import scenelib.annotations.el.AMethod;
import scenelib.annotations.el.ATypeElement;

/**
 * The methods of this class take an element or AST node, and return the annotated type as an {@link
 * AnnotatedTypeMirror}. The methods are:
 *
 * <ul>
 *   <li>{@link #getAnnotatedType(ClassTree)}
 *   <li>{@link #getAnnotatedType(MethodTree)}
 *   <li>{@link #getAnnotatedType(Tree)}
 *   <li>{@link #getAnnotatedTypeFromTypeTree(Tree)}
 *   <li>{@link #getAnnotatedType(TypeElement)}
 *   <li>{@link #getAnnotatedType(ExecutableElement)}
 *   <li>{@link #getAnnotatedType(Element)}
 * </ul>
 *
 * This implementation only adds qualifiers explicitly specified by the programmer. Subclasses
 * override {@link #addComputedTypeAnnotations} to add defaults, flow-sensitive refinement, and
 * type-system-specific rules.
 *
 * <p>Unless otherwise indicated, each public method in this class returns a "fully annotated" type,
 * which is one that has an annotation in all positions.
 *
 * <p>Type system checker writers may need to subclass this class, to add default qualifiers
 * according to the type system semantics. Subclasses should especially override {@link
 * #addComputedTypeAnnotations(Element, AnnotatedTypeMirror)} and {@link
 * #addComputedTypeAnnotations(Tree, AnnotatedTypeMirror)} to handle default annotations. (Also,
 * {@link #addDefaultAnnotations(AnnotatedTypeMirror)} adds annotations, but that method is a
 * workaround for <a href="https://github.com/typetools/checker-framework/issues/979">Issue
 * 979</a>.)
 *
 * @checker_framework.manual #creating-a-checker How to write a checker plug-in
 */
public class AnnotatedTypeFactory implements AnnotationProvider {

  /** Whether to print verbose debugging messages about stub files. */
  private final boolean debugStubParser;

  /** The {@link Trees} instance to use for tree node path finding. */
  protected final Trees trees;

  /** Optional! The AST of the source file being operated on. */
  // TODO: when should root be null? What are the use cases?
  // None of the existing test checkers has a null root.
  // Should not be modified between calls to "visit".
  protected @Nullable CompilationUnitTree root;

  /** The processing environment to use for accessing compiler internals. */
  protected final ProcessingEnvironment processingEnv;

  /** Utility class for working with {@link Element}s. */
  protected final Elements elements;

  /** Utility class for working with {@link TypeMirror}s. */
  public final Types types;

  /** The state of the visitor. */
  protected final VisitorState visitorState;

  /** The AnnotatedFor.value argument/element. */
  private final ExecutableElement annotatedForValueElement;
  /** The EnsuresQualifier.expression field/element. */
  final ExecutableElement ensuresQualifierExpressionElement;
  /** The EnsuresQualifier.List.value field/element. */
  final ExecutableElement ensuresQualifierListValueElement;
  /** The EnsuresQualifierIf.expression field/element. */
  final ExecutableElement ensuresQualifierIfExpressionElement;
  /** The EnsuresQualifierIf.result argument/element. */
  final ExecutableElement ensuresQualifierIfResultElement;
  /** The EnsuresQualifierIf.List.value field/element. */
  final ExecutableElement ensuresQualifierIfListValueElement;
  /** The FieldInvariant.field argument/element. */
  private final ExecutableElement fieldInvariantFieldElement;
  /** The FieldInvariant.qualifier argument/element. */
  private final ExecutableElement fieldInvariantQualifierElement;
  /** The HasQualifierParameter.value field/element. */
  private final ExecutableElement hasQualifierParameterValueElement;
  /** The MethodVal.className argument/element. */
  public final ExecutableElement methodValClassNameElement;
  /** The MethodVal.methodName argument/element. */
  public final ExecutableElement methodValMethodNameElement;
  /** The MethodVal.params argument/element. */
  public final ExecutableElement methodValParamsElement;
  /** The NoQualifierParameter.value field/element. */
  private final ExecutableElement noQualifierParameterValueElement;
  /** The RequiresQualifier.expression field/element. */
  final ExecutableElement requiresQualifierExpressionElement;
  /** The RequiresQualifier.List.value field/element. */
  final ExecutableElement requiresQualifierListValueElement;

  /** The RequiresQualifier type. */
  TypeMirror requiresQualifierTM;
  /** The RequiresQualifier.List type. */
  TypeMirror requiresQualifierListTM;
  /** The EnsuresQualifier type. */
  TypeMirror ensuresQualifierTM;
  /** The EnsuresQualifier.List type. */
  TypeMirror ensuresQualifierListTM;
  /** The EnsuresQualifierIf type. */
  TypeMirror ensuresQualifierIfTM;
  /** The EnsuresQualifierIf.List type. */
  TypeMirror ensuresQualifierIfListTM;

  /**
   * ===== postInit initialized fields ==== Note: qualHierarchy and typeHierarchy are both
   * initialized in the postInit.
   *
   * @see #postInit() This means, they cannot be final and cannot be referred to in any subclass
   *     constructor or method until after postInit is called
   */

  /** Represent the annotation relations. */
  protected QualifierHierarchy qualHierarchy;

  /** Represent the type relations. */
  protected TypeHierarchy typeHierarchy;

  /** Performs whole-program inference. If null, whole-program inference is disabled. */
  private final @Nullable WholeProgramInference wholeProgramInference;

  /**
   * This formatter is used for converting AnnotatedTypeMirrors to Strings. This formatter will be
   * used by all AnnotatedTypeMirrors created by this factory in their toString methods.
   */
  protected final AnnotatedTypeFormatter typeFormatter;

  /**
   * Annotation formatter is used to format AnnotationMirrors. It is primarily used by SourceChecker
   * when generating error messages.
   */
  private final AnnotationFormatter annotationFormatter;

  /** Holds the qualifier upper bounds for type uses. */
  protected QualifierUpperBounds qualifierUpperBounds;

  /**
   * Provides utility method to substitute arguments for their type variables. Field should be
   * final, but can only be set in postInit, because subtypes might need other state to be
   * initialized first.
   */
  protected TypeVariableSubstitutor typeVarSubstitutor;

  /** Provides utility method to infer type arguments. */
  protected TypeArgumentInference typeArgumentInference;

  /**
   * Caches the supported type qualifier classes. Call {@link #getSupportedTypeQualifiers()} instead
   * of using this field directly, as it may not have been initialized.
   */
  private final Set<Class<? extends Annotation>> supportedQuals;

  /**
   * Caches the fully-qualified names of the classes in {@link #supportedQuals}. Call {@link
   * #getSupportedTypeQualifierNames()} instead of using this field directly, as it may not have
   * been initialized.
   */
  private final Set<@CanonicalName String> supportedQualNames;

  /** Parses stub files and stores annotations on public elements from stub files. */
  public final AnnotationFileElementTypes stubTypes;

  /** Parses ajava files and stores annotations on public elements from ajava files. */
  public final AnnotationFileElementTypes ajavaTypes;

  /**
   * If type checking a Java file, stores annotations read from an ajava file for that class if one
   * exists. Unlike {@link #ajavaTypes}, which only stores annotations on public elements, this
   * stores annotations on all element locations such as in anonymous class bodies.
   */
  public @Nullable AnnotationFileElementTypes currentFileAjavaTypes;

  /**
   * A cache used to store elements whose declaration annotations have already been stored by
   * calling the method {@link #getDeclAnnotations(Element)}.
   */
  private final Map<Element, Set<AnnotationMirror>> cacheDeclAnnos;

  /**
   * A set containing declaration annotations that should be inherited. A declaration annotation
   * will be inherited if it is in this set, or if it has the meta-annotation @InheritedAnnotation.
   */
  private final Set<AnnotationMirror> inheritedAnnotations = AnnotationUtils.createAnnotationSet();

  /** The checker to use for option handling and resource management. */
  protected final BaseTypeChecker checker;

  /** Map keys are canonical names of aliased annotations. */
  private final Map<@FullyQualifiedName String, Alias> aliases = new HashMap<>();

  /**
   * Information about one annotation alias.
   *
   * <p>The information is either an AnotationMirror that can be used directly, or information for a
   * builder (name and fields not to copy); see checkRep.
   */
  private static class Alias {
    /** The canonical annotation (or null if copyElements == true). */
    AnnotationMirror canonical;
    /** Whether elements should be copied over when translating to the canonical annotation. */
    boolean copyElements;
    /** The canonical annotation name (or null if copyElements == false). */
    @CanonicalName String canonicalName;
    /** Which elements should not be copied over (or null if copyElements == false). */
    String[] ignorableElements;

    /**
     * Create an Alias with the given components.
     *
     * @param aliasName the alias name; only used for debugging
     * @param canonical the canonical annotation
     * @param copyElements whether elements should be copied over when translating to the canonical
     *     annotation
     * @param canonicalName the canonical annotation name (or null if copyElements == false)
     * @param ignorableElements elements that should not be copied over
     */
    Alias(
        String aliasName,
        AnnotationMirror canonical,
        boolean copyElements,
        @CanonicalName String canonicalName,
        String[] ignorableElements) {
      this.canonical = canonical;
      this.copyElements = copyElements;
      this.canonicalName = canonicalName;
      this.ignorableElements = ignorableElements;
      checkRep(aliasName);
    }

    /**
     * Throw an exception if this object is malformed.
     *
     * @param aliasName the alias name; only used for diagnostic messages
     */
    void checkRep(String aliasName) {
      if (copyElements) {
        if (!(canonical == null && canonicalName != null && ignorableElements != null)) {
          throw new BugInCF(
              "Bad Alias for %s: [canonical=%s] copyElements=%s canonicalName=%s"
                  + " ignorableElements=%s",
              aliasName, canonical, copyElements, canonicalName, ignorableElements);
        }
      } else {
        if (!(canonical != null && canonicalName == null && ignorableElements == null)) {
          throw new BugInCF(
              "Bad Alias for %s: canonical=%s copyElements=%s [canonicalName=%s"
                  + " ignorableElements=%s]",
              aliasName, canonical, copyElements, canonicalName, ignorableElements);
        }
      }
    }
  }

  /**
   * A map from the class of an annotation to the set of classes for annotations with the same
   * meaning, as well as the annotation mirror that should be used.
   */
  private final Map<
          Class<? extends Annotation>, Pair<AnnotationMirror, Set<Class<? extends Annotation>>>>
      declAliases = new HashMap<>();

  /** Unique ID counter; for debugging purposes. */
  private static int uidCounter = 0;

  /** Unique ID of the current object; for debugging purposes. */
  public final int uid;

  /**
   * Object that is used to resolve reflective method calls, if reflection resolution is turned on.
   */
  protected ReflectionResolver reflectionResolver;

  /** AnnotationClassLoader used to load type annotation classes via reflective lookup. */
  protected AnnotationClassLoader loader;

  /**
   * Which whole-program inference output format to use, if doing whole-program inference. This
   * variable would be final, but it is not set unless WPI is enabled.
   */
  protected WholeProgramInference.OutputFormat wpiOutputFormat;

  /**
   * Should results be cached? This means that ATM.deepCopy() will be called. ATM.deepCopy() used to
   * (and perhaps still does) side effect the ATM being copied. So setting this to false is not
   * equivalent to setting shouldReadCache to false.
   */
  public boolean shouldCache;

  /** Size of LRU cache if one isn't specified using the atfCacheSize option. */
  private static final int DEFAULT_CACHE_SIZE = 300;

  /** Mapping from a Tree to its annotated type; defaults have been applied. */
  private final Map<Tree, AnnotatedTypeMirror> classAndMethodTreeCache;

  /**
   * Mapping from an expression tree to its annotated type; before defaults are applied, just what
   * the programmer wrote.
   */
  protected final Map<Tree, AnnotatedTypeMirror> fromExpressionTreeCache;

  /**
   * Mapping from a member tree to its annotated type; before defaults are applied, just what the
   * programmer wrote.
   */
  protected final Map<Tree, AnnotatedTypeMirror> fromMemberTreeCache;

  /**
   * Mapping from a type tree to its annotated type; before defaults are applied, just what the
   * programmer wrote.
   */
  protected final Map<Tree, AnnotatedTypeMirror> fromTypeTreeCache;

  /**
   * Mapping from an Element to its annotated type; before defaults are applied, just what the
   * programmer wrote.
   */
  private final Map<Element, AnnotatedTypeMirror> elementCache;

  /** Mapping from an Element to the source Tree of the declaration. */
  private final Map<Element, Tree> elementToTreeCache;

  /** Mapping from a Tree to its TreePath. Shared between all instances. */
  private final TreePathCacher treePathCache;

  /** Mapping from CFG-generated trees to their enclosing elements. */
  protected final Map<Tree, Element> artificialTreeToEnclosingElementMap;

  /**
   * Whether to ignore uninferred type arguments. This is a temporary flag to work around Issue 979.
   */
  public final boolean ignoreUninferredTypeArguments;

  /** The Object.getClass method. */
  protected final ExecutableElement objectGetClass;

  /** Size of the annotationClassNames cache. */
  private static final int ANNOTATION_CACHE_SIZE = 500;

  /** Maps classes representing AnnotationMirrors to their canonical names. */
  private final Map<Class<? extends Annotation>, @CanonicalName String> annotationClassNames;

  /** An annotated type of the declaration of {@link Iterable} without any annotations. */
  private AnnotatedDeclaredType iterableDeclType;

  /**
   * Constructs a factory from the given {@link ProcessingEnvironment} instance and syntax tree
   * root. (These parameters are required so that the factory may conduct the appropriate
   * annotation-gathering analyses on certain tree types.)
   *
   * <p>Root can be {@code null} if the factory does not operate on trees.
   *
   * <p>A subclass must call postInit at the end of its constructor. postInit must be the last call
   * in the constructor or else types from stub files may not be created as expected.
   *
   * @param checker the {@link SourceChecker} to which this factory belongs
   * @throws IllegalArgumentException if either argument is {@code null}
   */
  public AnnotatedTypeFactory(BaseTypeChecker checker) {
    uid = ++uidCounter;
    this.processingEnv = checker.getProcessingEnvironment();
    // this.root = root;
    this.checker = checker;
    this.trees = Trees.instance(processingEnv);
    this.elements = processingEnv.getElementUtils();
    this.types = processingEnv.getTypeUtils();
    this.visitorState = new VisitorState();

    this.supportedQuals = new HashSet<>();
    this.supportedQualNames = new HashSet<>();
    this.stubTypes = new AnnotationFileElementTypes(this);
    this.ajavaTypes = new AnnotationFileElementTypes(this);
    this.currentFileAjavaTypes = null;

    this.cacheDeclAnnos = new HashMap<>();

    this.artificialTreeToEnclosingElementMap = new HashMap<>();
    // get the shared instance from the checker
    this.treePathCache = checker.getTreePathCacher();

    this.shouldCache = !checker.hasOption("atfDoNotCache");
    if (shouldCache) {
      int cacheSize = getCacheSize();
      this.classAndMethodTreeCache = CollectionUtils.createLRUCache(cacheSize);
      this.fromExpressionTreeCache = CollectionUtils.createLRUCache(cacheSize);
      this.fromMemberTreeCache = CollectionUtils.createLRUCache(cacheSize);
      this.fromTypeTreeCache = CollectionUtils.createLRUCache(cacheSize);
      this.elementCache = CollectionUtils.createLRUCache(cacheSize);
      this.elementToTreeCache = CollectionUtils.createLRUCache(cacheSize);
      this.annotationClassNames =
          Collections.synchronizedMap(CollectionUtils.createLRUCache(ANNOTATION_CACHE_SIZE));
    } else {
      this.classAndMethodTreeCache = null;
      this.fromExpressionTreeCache = null;
      this.fromMemberTreeCache = null;
      this.fromTypeTreeCache = null;
      this.elementCache = null;
      this.elementToTreeCache = null;
      this.annotationClassNames = null;
    }

    this.typeFormatter = createAnnotatedTypeFormatter();
    this.annotationFormatter = createAnnotationFormatter();

    if (checker.hasOption("infer")) {
      checkInvalidOptionsInferSignatures();
      String inferArg = checker.getOption("infer");
      // No argument means "jaifs", for (temporary) backwards compatibility.
      if (inferArg == null) {
        inferArg = "jaifs";
      }
      switch (inferArg) {
        case "stubs":
          wpiOutputFormat = WholeProgramInference.OutputFormat.STUB;
          break;
        case "jaifs":
          wpiOutputFormat = WholeProgramInference.OutputFormat.JAIF;
          break;
        case "ajava":
          wpiOutputFormat = WholeProgramInference.OutputFormat.AJAVA;
          break;
        default:
          throw new UserError(
              "Bad argument -Ainfer="
                  + inferArg
                  + " should be one of: -Ainfer=jaifs, -Ainfer=stubs, -Ainfer=ajava");
      }
      if (wpiOutputFormat == WholeProgramInference.OutputFormat.AJAVA) {
        wholeProgramInference =
            new WholeProgramInferenceImplementation<AnnotatedTypeMirror>(
                this, new WholeProgramInferenceJavaParserStorage(this));
      } else {
        wholeProgramInference =
            new WholeProgramInferenceImplementation<ATypeElement>(
                this, new WholeProgramInferenceScenesStorage(this));
      }
      if (!checker.hasOption("warns")) {
        // Without -Awarns, the inference output may be incomplete, because javac halts
        // after issuing an error.
        checker.message(Diagnostic.Kind.ERROR, "Do not supply -Ainfer without -Awarns");
      }
    } else {
      wholeProgramInference = null;
    }
    ignoreUninferredTypeArguments = !checker.hasOption("conservativeUninferredTypeArguments");

    objectGetClass = TreeUtils.getMethod("java.lang.Object", "getClass", 0, processingEnv);

    this.debugStubParser = checker.hasOption("stubDebug");

    annotatedForValueElement = TreeUtils.getMethod(AnnotatedFor.class, "value", 0, processingEnv);
    ensuresQualifierExpressionElement =
        TreeUtils.getMethod(EnsuresQualifier.class, "expression", 0, processingEnv);
    ensuresQualifierListValueElement =
        TreeUtils.getMethod(EnsuresQualifier.List.class, "value", 0, processingEnv);
    ensuresQualifierIfExpressionElement =
        TreeUtils.getMethod(EnsuresQualifierIf.class, "expression", 0, processingEnv);
    ensuresQualifierIfResultElement =
        TreeUtils.getMethod(EnsuresQualifierIf.class, "result", 0, processingEnv);
    ensuresQualifierIfListValueElement =
        TreeUtils.getMethod(EnsuresQualifierIf.List.class, "value", 0, processingEnv);
    fieldInvariantFieldElement =
        TreeUtils.getMethod(FieldInvariant.class, "field", 0, processingEnv);
    fieldInvariantQualifierElement =
        TreeUtils.getMethod(FieldInvariant.class, "qualifier", 0, processingEnv);
    hasQualifierParameterValueElement =
        TreeUtils.getMethod(HasQualifierParameter.class, "value", 0, processingEnv);
    methodValClassNameElement = TreeUtils.getMethod(MethodVal.class, "className", 0, processingEnv);
    methodValMethodNameElement =
        TreeUtils.getMethod(MethodVal.class, "methodName", 0, processingEnv);
    methodValParamsElement = TreeUtils.getMethod(MethodVal.class, "params", 0, processingEnv);
    noQualifierParameterValueElement =
        TreeUtils.getMethod(NoQualifierParameter.class, "value", 0, processingEnv);
    requiresQualifierExpressionElement =
        TreeUtils.getMethod(RequiresQualifier.class, "expression", 0, processingEnv);
    requiresQualifierListValueElement =
        TreeUtils.getMethod(RequiresQualifier.List.class, "value", 0, processingEnv);

    requiresQualifierTM =
        ElementUtils.getTypeElement(processingEnv, RequiresQualifier.class).asType();
    requiresQualifierListTM =
        ElementUtils.getTypeElement(processingEnv, RequiresQualifier.List.class).asType();
    ensuresQualifierTM =
        ElementUtils.getTypeElement(processingEnv, EnsuresQualifier.class).asType();
    ensuresQualifierListTM =
        ElementUtils.getTypeElement(processingEnv, EnsuresQualifier.List.class).asType();
    ensuresQualifierIfTM =
        ElementUtils.getTypeElement(processingEnv, EnsuresQualifierIf.class).asType();
    ensuresQualifierIfListTM =
        ElementUtils.getTypeElement(processingEnv, EnsuresQualifierIf.List.class).asType();
  }

  /**
   * @throws BugInCF If supportedQuals is empty or if any of the support qualifiers has a @Target
   *     meta-annotation that contain something besides TYPE_USE or TYPE_PARAMETER. (@Target({}) is
   *     allowed.)
   */
  private void checkSupportedQuals() {
    if (supportedQuals.isEmpty()) {
      throw new TypeSystemError("Found no supported qualifiers.");
    }
    for (Class<? extends Annotation> annotationClass : supportedQuals) {
      // Check @Target values
      ElementType[] targetValues = annotationClass.getAnnotation(Target.class).value();
      List<ElementType> badTargetValues = new ArrayList<>();
      for (ElementType element : targetValues) {
        if (!(element == ElementType.TYPE_USE || element == ElementType.TYPE_PARAMETER)) {
          // if there's an ElementType with an enumerated value of something other
          // than TYPE_USE or TYPE_PARAMETER then it isn't a valid qualifier
          badTargetValues.add(element);
        }
      }
      if (!badTargetValues.isEmpty()) {
        String msg =
            "The @Target meta-annotation on type qualifier "
                + annotationClass.toString()
                + " must not contain "
                + StringsPlume.conjunction("or", badTargetValues)
                + ".";
        throw new TypeSystemError(msg);
      }
    }
  }

  /**
   * This method is called only when {@code -Ainfer} is passed as an option. It checks if another
   * option that should not occur simultaneously with the whole-program inference is also passed as
   * argument, and aborts the process if that is the case. For example, the whole-program inference
   * process was not designed to work with conservative defaults.
   *
   * <p>Subclasses may override this method to add more options.
   */
  protected void checkInvalidOptionsInferSignatures() {
    // See Issue 683
    // https://github.com/typetools/checker-framework/issues/683
    if (checker.useConservativeDefault("source") || checker.useConservativeDefault("bytecode")) {
      throw new UserError(
          "The option -Ainfer=... cannot be used together with conservative defaults.");
    }
  }

  /**
   * Actions that logically belong in the constructor, but need to run after the subclass
   * constructor has completed. In particular, parseStubFiles() may try to do type resolution with
   * this AnnotatedTypeFactory.
   */
  protected void postInit() {
    this.qualHierarchy = createQualifierHierarchy();
    if (qualHierarchy == null) {
      throw new TypeSystemError(
          "AnnotatedTypeFactory with null qualifier hierarchy not supported.");
    } else if (!qualHierarchy.isValid()) {
      throw new TypeSystemError(
          "AnnotatedTypeFactory: invalid qualifier hierarchy: %s %s ",
          qualHierarchy.getClass(), qualHierarchy);
    }
    this.typeHierarchy = createTypeHierarchy();
    this.typeVarSubstitutor = createTypeVariableSubstitutor();
    this.typeArgumentInference = createTypeArgumentInference();
    this.qualifierUpperBounds = createQualifierUpperBounds();

    // TODO: is this the best location for declaring this alias?
    addAliasedDeclAnnotation(
        org.jmlspecs.annotation.Pure.class,
        org.checkerframework.dataflow.qual.Pure.class,
        AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.Pure.class));

    // Accommodate the inability to write @InheritedAnnotation on these annotations.
    addInheritedAnnotation(
        AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.Pure.class));
    addInheritedAnnotation(
        AnnotationBuilder.fromClass(
            elements, org.checkerframework.dataflow.qual.SideEffectFree.class));
    addInheritedAnnotation(
        AnnotationBuilder.fromClass(
            elements, org.checkerframework.dataflow.qual.Deterministic.class));
    addInheritedAnnotation(
        AnnotationBuilder.fromClass(
            elements, org.checkerframework.dataflow.qual.TerminatesExecution.class));

    initializeReflectionResolution();

    if (this.getClass() == AnnotatedTypeFactory.class) {
      this.parseAnnotationFiles();
    }
    TypeMirror iterableTypeMirror =
        ElementUtils.getTypeElement(processingEnv, Iterable.class).asType();
    this.iterableDeclType =
        (AnnotatedDeclaredType) AnnotatedTypeMirror.createType(iterableTypeMirror, this, true);
  }

  /**
   * Returns the checker associated with this factory.
   *
   * @return the checker associated with this factory
   */
  public BaseTypeChecker getChecker() {
    return checker;
  }

  /**
   * Creates {@link QualifierUpperBounds} for this type factory.
   *
   * @return a new {@link QualifierUpperBounds} for this type factory
   */
  protected QualifierUpperBounds createQualifierUpperBounds() {
    return new QualifierUpperBounds(this);
  }

  /**
   * Return {@link QualifierUpperBounds} for this type factory.
   *
   * @return {@link QualifierUpperBounds} for this type factory
   */
  public QualifierUpperBounds getQualifierUpperBounds() {
    return qualifierUpperBounds;
  }

  /**
   * Returns the WholeProgramInference instance (may be null).
   *
   * @return the WholeProgramInference instance, or null
   */
  public WholeProgramInference getWholeProgramInference() {
    return wholeProgramInference;
  }

  protected void initializeReflectionResolution() {
    if (checker.shouldResolveReflection()) {
      boolean debug = "debug".equals(checker.getOption("resolveReflection"));

      MethodValChecker methodValChecker = checker.getSubchecker(MethodValChecker.class);
      assert methodValChecker != null
          : "AnnotatedTypeFactory: reflection resolution was requested, but MethodValChecker isn't"
              + " a subchecker.";
      MethodValAnnotatedTypeFactory methodValATF =
          (MethodValAnnotatedTypeFactory) methodValChecker.getAnnotationProvider();

      reflectionResolver = new DefaultReflectionResolver(checker, methodValATF, debug);
    }
  }

  /**
   * Set the CompilationUnitTree that should be used.
   *
   * @param root the new compilation unit to use
   */
  public void setRoot(@Nullable CompilationUnitTree root) {
    if (root != null && wholeProgramInference != null) {
      for (Tree typeDecl : root.getTypeDecls()) {
        if (typeDecl.getKind() == Kind.CLASS) {
          ClassTree classTree = (ClassTree) typeDecl;
          wholeProgramInference.preprocessClassTree(classTree);
        }
      }
    }

    this.root = root;
    // Do not clear here. Only the primary checker should clear this cache.
    // treePathCache.clear();

    // setRoot in a GenericAnnotatedTypeFactory will clear this;
    // if this isn't a GenericATF, then it must clear it itself.
    if (!(this instanceof GenericAnnotatedTypeFactory)) {
      artificialTreeToEnclosingElementMap.clear();
    }

    if (shouldCache) {
      // Clear the caches with trees because once the compilation unit changes,
      // the trees may be modified and lose type arguments.
      elementToTreeCache.clear();
      fromExpressionTreeCache.clear();
      fromMemberTreeCache.clear();
      fromTypeTreeCache.clear();
      classAndMethodTreeCache.clear();

      // There is no need to clear the following cache, it is limited by cache size and it
      // contents won't change between compilation units.
      // elementCache.clear();
    }

    if (root != null && checker.hasOption("ajava")) {
      // Search for an ajava file with annotations for the current source file and the current
      // checker. It will be in a directory specified by the "ajava" option in a subdirectory
      // corresponding to this file's package. For example, a file in package a.b would be in a
      // subdirectory a/b. The filename is ClassName-checker.qualified.name.ajava. If such a file
      // exists, read its detailed annotation data, including annotations on private elements.

      String packagePrefix =
          root.getPackageName() != null
              ? TreeUtils.nameExpressionToString(root.getPackageName()) + "."
              : "";

      // The method getName() returns a path.
      String className = root.getSourceFile().getName();
      // Extract the basename.
      int lastSeparator = className.lastIndexOf(File.separator);
      if (lastSeparator != -1) {
        className = className.substring(lastSeparator + 1);
      }
      // Drop the ".java" extension.
      if (className.endsWith(".java")) {
        className = className.substring(0, className.length() - ".java".length());
      }

      String qualifiedName = packagePrefix + className;

      for (String ajavaLocation : checker.getOption("ajava").split(File.pathSeparator)) {
        String ajavaPath =
            ajavaLocation
                + File.separator
                + qualifiedName.replaceAll("\\.", "/")
                + "-"
                + checker.getClass().getCanonicalName()
                + ".ajava";
        File ajavaFile = new File(ajavaPath);
        if (ajavaFile.exists()) {
          currentFileAjavaTypes = new AnnotationFileElementTypes(this);
          currentFileAjavaTypes.parseAjavaFileWithTree(ajavaPath, root);
          break;
        }
      }
    } else {
      currentFileAjavaTypes = null;
    }
  }

  @SideEffectFree
  @Override
  public String toString() {
    return getClass().getSimpleName() + "#" + uid;
  }

  /**
   * Returns the {@link QualifierHierarchy} to be used by this checker.
   *
   * <p>The implementation builds the type qualifier hierarchy for the {@link
   * #getSupportedTypeQualifiers()} using the meta-annotations found in them. The current
   * implementation returns an instance of {@code NoElementQualifierHierarchy}.
   *
   * <p>Subclasses must override this method if their qualifiers have elements; the method must
   * return an implementation of {@link QualifierHierarchy}, such as {@link
   * ElementQualifierHierarchy}.
   *
   * @return a QualifierHierarchy for this type system
   */
  protected QualifierHierarchy createQualifierHierarchy() {
    return new NoElementQualifierHierarchy(this.getSupportedTypeQualifiers(), elements);
  }

  /**
   * Returns the type qualifier hierarchy graph to be used by this processor.
   *
   * @see #createQualifierHierarchy()
   * @return the {@link QualifierHierarchy} for this checker
   */
  public final QualifierHierarchy getQualifierHierarchy() {
    return qualHierarchy;
  }

  /**
   * To continue to use a subclass of {@link
   * org.checkerframework.framework.util.MultiGraphQualifierHierarchy} or {@link
   * org.checkerframework.framework.util.GraphQualifierHierarchy}, override this method so that it
   * returns a new instance of the subclass. Then override {@link #createQualifierHierarchy()} so
   * that it returns the result of a call to {@link
   * org.checkerframework.framework.util.MultiGraphQualifierHierarchy#createMultiGraphQualifierHierarchy(AnnotatedTypeFactory)}.
   *
   * @param factory MultiGraphFactory
   * @return QualifierHierarchy
   * @deprecated Use either {@link ElementQualifierHierarchy}, {@link NoElementQualifierHierarchy},
   *     or {@link MostlyNoElementQualifierHierarchy} instead. This method will be removed in a
   *     future release.
   */
  @Deprecated // 2020-09-10
  public QualifierHierarchy createQualifierHierarchyWithMultiGraphFactory(
      org.checkerframework.framework.util.MultiGraphQualifierHierarchy.MultiGraphFactory factory) {
    throw new TypeSystemError(
        "Checker must override AnnotatedTypeFactory#createQualifierHierarchyWithMultiGraphFactory"
            + " when using AnnotatedTypeFactory#createMultiGraphQualifierHierarchy.");
  }

  /**
   * Creates the type hierarchy to be used by this factory.
   *
   * <p>Subclasses may override this method to specify new type-checking rules beyond the typical
   * Java subtyping rules.
   *
   * @return the type relations class to check type subtyping
   */
  protected TypeHierarchy createTypeHierarchy() {
    return new DefaultTypeHierarchy(
        checker,
        getQualifierHierarchy(),
        checker.getBooleanOption("ignoreRawTypeArguments", true),
        checker.hasOption("invariantArrays"));
  }

  public final TypeHierarchy getTypeHierarchy() {
    return typeHierarchy;
  }

  /** TypeVariableSubstitutor provides a method to replace type parameters with their arguments. */
  protected TypeVariableSubstitutor createTypeVariableSubstitutor() {
    return new TypeVariableSubstitutor();
  }

  public TypeVariableSubstitutor getTypeVarSubstitutor() {
    return typeVarSubstitutor;
  }

  /**
   * TypeArgumentInference infers the method type arguments when they are not explicitly written.
   */
  protected TypeArgumentInference createTypeArgumentInference() {
    return new DefaultTypeArgumentInference(this);
  }

  public TypeArgumentInference getTypeArgumentInference() {
    return typeArgumentInference;
  }

  /**
   * Factory method to easily change what {@link AnnotationClassLoader} is created to load type
   * annotation classes. Subclasses can override this method and return a custom
   * AnnotationClassLoader subclass to customize loading logic.
   */
  protected AnnotationClassLoader createAnnotationClassLoader() {
    return new AnnotationClassLoader(checker);
  }

  /**
   * Returns a mutable set of annotation classes that are supported by a checker.
   *
   * <p>Subclasses may override this method to return a mutable set of their supported type
   * qualifiers through one of the 5 approaches shown below.
   *
   * <p>Subclasses should not call this method; they should call {@link #getSupportedTypeQualifiers}
   * instead.
   *
   * <p>By default, a checker supports all annotations located in a subdirectory called {@literal
   * qual} that's located in the same directory as the checker. Note that only annotations defined
   * with the {@code @Target({ElementType.TYPE_USE})} meta-annotation (and optionally with the
   * additional value of {@code ElementType.TYPE_PARAMETER}, but no other {@code ElementType}
   * values) are automatically considered as supported annotations.
   *
   * <p>To support a different set of annotations than those in the {@literal qual} subdirectory, or
   * that have other {@code ElementType} values, see examples below.
   *
   * <p>In total, there are 5 ways to indicate annotations that are supported by a checker:
   *
   * <ol>
   *   <li>Only support annotations located in a checker's {@literal qual} directory:
   *       <p>This is the default behavior. Simply place those annotations within the {@literal
   *       qual} directory.
   *   <li>Support annotations located in a checker's {@literal qual} directory and a list of other
   *       annotations:
   *       <p>Place those annotations within the {@literal qual} directory, and override {@link
   *       #createSupportedTypeQualifiers()} by calling {@link #getBundledTypeQualifiers(Class...)}
   *       with a varargs parameter list of the other annotations. Code example:
   *       <pre>
   * {@code @Override protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
   *      return getBundledTypeQualifiers(Regex.class, PartialRegex.class, RegexBottom.class, UnknownRegex.class);
   *  } }
   * </pre>
   *   <li>Supporting only annotations that are explicitly listed: Override {@link
   *       #createSupportedTypeQualifiers()} and return a mutable set of the supported annotations.
   *       Code example:
   *       <pre>
   * {@code @Override protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
   *      return new HashSet<Class<? extends Annotation>>(
   *              Arrays.asList(A.class, B.class));
   *  } }
   * </pre>
   *       The set of qualifiers returned by {@link #createSupportedTypeQualifiers()} must be a
   *       fresh, mutable set. The methods {@link #getBundledTypeQualifiers(Class...)} must return a
   *       fresh, mutable set
   * </ol>
   *
   * @return the type qualifiers supported this processor, or an empty set if none
   */
  protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
    return getBundledTypeQualifiers();
  }

  /**
   * Loads all annotations contained in the qual directory of a checker via reflection; if a
   * polymorphic type qualifier exists, and an explicit array of annotations to the set of
   * annotation classes.
   *
   * <p>This method can be called in the overridden versions of {@link
   * #createSupportedTypeQualifiers()} in each checker.
   *
   * @param explicitlyListedAnnotations a varargs array of explicitly listed annotation classes to
   *     be added to the returned set. For example, it is used frequently to add Bottom qualifiers.
   * @return a mutable set of the loaded and listed annotation classes
   */
  @SafeVarargs
  protected final Set<Class<? extends Annotation>> getBundledTypeQualifiers(
      Class<? extends Annotation>... explicitlyListedAnnotations) {
    return loadTypeAnnotationsFromQualDir(explicitlyListedAnnotations);
  }

  /**
   * Instantiates the AnnotationClassLoader and loads all annotations contained in the qual
   * directory of a checker via reflection, and has the option to include an explicitly stated list
   * of annotations (eg ones found in a different directory than qual).
   *
   * <p>The annotations that are automatically loaded must have the {@link
   * java.lang.annotation.Target Target} meta-annotation with the value of {@link
   * ElementType#TYPE_USE} (and optionally {@link ElementType#TYPE_PARAMETER}). If it has other
   * {@link ElementType} values, it won't be loaded. Other annotation classes must be explicitly
   * listed even if they are in the same directory as the checker's qual directory.
   *
   * @param explicitlyListedAnnotations a set of explicitly listed annotation classes to be added to
   *     the returned set, for example, it is used frequently to add Bottom qualifiers
   * @return a set of annotation class instances
   */
  @SafeVarargs
  @SuppressWarnings("varargs")
  private final Set<Class<? extends Annotation>> loadTypeAnnotationsFromQualDir(
      Class<? extends Annotation>... explicitlyListedAnnotations) {
    loader = createAnnotationClassLoader();

    Set<Class<? extends Annotation>> annotations = loader.getBundledAnnotationClasses();

    // add in all explicitly Listed qualifiers
    if (explicitlyListedAnnotations != null) {
      annotations.addAll(Arrays.asList(explicitlyListedAnnotations));
    }

    return annotations;
  }

  /**
   * Creates the AnnotatedTypeFormatter used by this type factory and all AnnotatedTypeMirrors it
   * creates. The AnnotatedTypeFormatter is used in AnnotatedTypeMirror.toString and will affect the
   * error messages printed for checkers that use this type factory.
   *
   * @return the AnnotatedTypeFormatter to pass to all instantiated AnnotatedTypeMirrors
   */
  protected AnnotatedTypeFormatter createAnnotatedTypeFormatter() {
    boolean printVerboseGenerics = checker.hasOption("printVerboseGenerics");
    return new DefaultAnnotatedTypeFormatter(
        printVerboseGenerics,
        // -AprintVerboseGenerics implies -AprintAllQualifiers
        printVerboseGenerics || checker.hasOption("printAllQualifiers"));
  }

  public AnnotatedTypeFormatter getAnnotatedTypeFormatter() {
    return typeFormatter;
  }

  protected AnnotationFormatter createAnnotationFormatter() {
    return new DefaultAnnotationFormatter();
  }

  public AnnotationFormatter getAnnotationFormatter() {
    return annotationFormatter;
  }

  /**
   * Returns an immutable set of the classes corresponding to the type qualifiers supported by this
   * checker.
   *
   * <p>Subclasses cannot override this method; they should override {@link
   * #createSupportedTypeQualifiers createSupportedTypeQualifiers} instead.
   *
   * @see #createSupportedTypeQualifiers()
   * @return an immutable set of the supported type qualifiers, or an empty set if no qualifiers are
   *     supported
   */
  public final Set<Class<? extends Annotation>> getSupportedTypeQualifiers() {
    if (this.supportedQuals.isEmpty()) {
      supportedQuals.addAll(createSupportedTypeQualifiers());
      checkSupportedQuals();
    }
    return Collections.unmodifiableSet(supportedQuals);
  }

  /**
   * Returns an immutable set of the fully qualified names of the type qualifiers supported by this
   * checker.
   *
   * <p>Subclasses cannot override this method; they should override {@link
   * #createSupportedTypeQualifiers createSupportedTypeQualifiers} instead.
   *
   * @see #createSupportedTypeQualifiers()
   * @return an immutable set of the supported type qualifiers, or an empty set if no qualifiers are
   *     supported
   */
  public final Set<@CanonicalName String> getSupportedTypeQualifierNames() {
    if (this.supportedQualNames.isEmpty()) {
      for (Class<?> clazz : getSupportedTypeQualifiers()) {
        supportedQualNames.add(clazz.getCanonicalName());
      }
    }
    return Collections.unmodifiableSet(supportedQualNames);
  }

  // **********************************************************************
  // Factories for annotated types that account for default qualifiers
  // **********************************************************************

  /**
   * Returns the size for LRU caches. It is either the value supplied via the {@code -AatfCacheSize}
   * option or the default cache size.
   *
   * @return cache size passed as argument to checker or DEFAULT_CACHE_SIZE
   */
  protected int getCacheSize() {
    String option = checker.getOption("atfCacheSize");
    if (option == null) {
      return DEFAULT_CACHE_SIZE;
    }
    try {
      return Integer.valueOf(option);
    } catch (NumberFormatException ex) {
      throw new UserError("atfCacheSize was not an integer: " + option);
    }
  }

  /**
   * Returns an AnnotatedTypeMirror representing the annotated type of {@code elt}.
   *
   * @param elt the element
   * @return the annotated type of {@code elt}
   */
  public AnnotatedTypeMirror getAnnotatedType(Element elt) {
    if (elt == null) {
      throw new BugInCF("AnnotatedTypeFactory.getAnnotatedType: null element");
    }
    // Annotations explicitly written in the source code,
    // or obtained from bytecode.
    AnnotatedTypeMirror type = fromElement(elt);
    addComputedTypeAnnotations(elt, type);
    return type;
  }

  /**
   * Returns an AnnotatedTypeMirror representing the annotated type of {@code clazz}.
   *
   * @param clazz a class
   * @return the annotated type of {@code clazz}
   */
  public AnnotatedTypeMirror getAnnotatedType(Class<?> clazz) {
    return getAnnotatedType(elements.getTypeElement(clazz.getCanonicalName()));
  }

  @Override
  public @Nullable AnnotationMirror getAnnotationMirror(
      Tree tree, Class<? extends Annotation> target) {
    if (isSupportedQualifier(target)) {
      AnnotatedTypeMirror atm = getAnnotatedType(tree);
      return atm.getAnnotation(target);
    }
    return null;
  }

  /**
   * Returns an AnnotatedTypeMirror representing the annotated type of {@code tree}.
   *
   * @param tree the AST node
   * @return the annotated type of {@code tree}
   */
  public AnnotatedTypeMirror getAnnotatedType(Tree tree) {

    if (tree == null) {
      throw new BugInCF("AnnotatedTypeFactory.getAnnotatedType: null tree");
    }
    if (shouldCache && classAndMethodTreeCache.containsKey(tree)) {
      return classAndMethodTreeCache.get(tree).deepCopy();
    }

    AnnotatedTypeMirror type;
    if (TreeUtils.isClassTree(tree)) {
      type = fromClass((ClassTree) tree);
    } else if (tree.getKind() == Tree.Kind.METHOD || tree.getKind() == Tree.Kind.VARIABLE) {
      type = fromMember(tree);
    } else if (TreeUtils.isExpressionTree(tree)) {
      tree = TreeUtils.withoutParens((ExpressionTree) tree);
      type = fromExpression((ExpressionTree) tree);
    } else {
      throw new BugInCF(
          "AnnotatedTypeFactory.getAnnotatedType: query of annotated type for tree "
              + tree.getKind());
    }

    addComputedTypeAnnotations(tree, type);

    if (TreeUtils.isClassTree(tree) || tree.getKind() == Tree.Kind.METHOD) {
      // Don't cache VARIABLE
      if (shouldCache) {
        classAndMethodTreeCache.put(tree, type.deepCopy());
      }
    } else {
      // No caching otherwise
    }

    return type;
  }

  /**
   * Called by {@link BaseTypeVisitor#visitClass(ClassTree, Void)} before the classTree is type
   * checked.
   *
   * @param classTree ClassTree on which to perform preprocessing
   */
  public void preProcessClassTree(ClassTree classTree) {}

  /**
   * Called by {@link BaseTypeVisitor#visitClass(ClassTree, Void)} after the ClassTree has been type
   * checked.
   *
   * <p>The default implementation uses this to store the defaulted AnnotatedTypeMirrors and
   * inherited declaration annotations back into the corresponding Elements. Subclasses might want
   * to override this method if storing defaulted types is not desirable.
   */
  public void postProcessClassTree(ClassTree tree) {
    TypesIntoElements.store(processingEnv, this, tree);
    DeclarationsIntoElements.store(processingEnv, this, tree);
    if (wholeProgramInference != null) {
      // Write out the results of whole-program inference, just once for each class.  As soon as any
      // class is finished processing, all modified scenes are written to files, in case this was
      // the last class to be processed.  Post-processing of subsequent classes might result in
      // re-writing some of the scenes if new information has been written to them.
      wholeProgramInference.writeResultsToFile(wpiOutputFormat, this.checker);
    }
  }

  /**
   * Determines the annotated type from a type in tree form.
   *
   * <p>Note that we cannot decide from a Tree whether it is a type use or an expression.
   * TreeUtils.isTypeTree is only an under-approximation. For example, an identifier can be either a
   * type or an expression.
   *
   * @param tree the type tree
   * @return the annotated type of the type in the AST
   */
  public AnnotatedTypeMirror getAnnotatedTypeFromTypeTree(Tree tree) {
    if (tree == null) {
      throw new BugInCF("AnnotatedTypeFactory.getAnnotatedTypeFromTypeTree: null tree");
    }
    AnnotatedTypeMirror type = fromTypeTree(tree);
    addComputedTypeAnnotations(tree, type);
    return type;
  }

  /**
   * Returns the set of qualifiers that are the upper bounds for a use of the type.
   *
   * @param type a type whose upper bounds to obtain
   */
  public Set<AnnotationMirror> getTypeDeclarationBounds(TypeMirror type) {
    return qualifierUpperBounds.getBoundQualifiers(type);
  }

  /**
   * Returns the set of qualifiers that are the upper bound for a type use if no other bound is
   * specified for the type.
   *
   * <p>This implementation returns the top qualifiers by default. Subclass may override to return
   * different qualifiers.
   *
   * @return the set of qualifiers that are the upper bound for a type use if no other bound is
   *     specified for the type
   */
  protected Set<? extends AnnotationMirror> getDefaultTypeDeclarationBounds() {
    return qualHierarchy.getTopAnnotations();
  }

  /**
   * Returns the type of the extends or implements clause.
   *
   * <p>The primary qualifier is either an explicit annotation on {@code clause}, or it is the
   * qualifier upper bounds for uses of the type of the clause.
   *
   * @param clause tree that represents an extends or implements clause
   * @return the type of the extends or implements clause
   */
  public AnnotatedTypeMirror getTypeOfExtendsImplements(Tree clause) {
    AnnotatedTypeMirror fromTypeTree = fromTypeTree(clause);
    Set<AnnotationMirror> bound = getTypeDeclarationBounds(fromTypeTree.getUnderlyingType());
    fromTypeTree.addMissingAnnotations(bound);
    return fromTypeTree;
  }

  // **********************************************************************
  // Factories for annotated types that do not account for default qualifiers.
  // They only include qualifiers explicitly inserted by the user.
  // **********************************************************************

  /**
   * Creates an AnnotatedTypeMirror for {@code elt} that includes: annotations explicitly written on
   * the element and annotations from stub files.
   *
   * <p>Does not include default qualifiers. To obtain them, use {@link #getAnnotatedType(Element)}.
   *
   * <p>Does not include fake overrides from the stub file.
   *
   * @param elt the element
   * @return AnnotatedTypeMirror of the element with explicitly-written and stub file annotations
   */
  public AnnotatedTypeMirror fromElement(Element elt) {
    if (shouldCache && elementCache.containsKey(elt)) {
      return elementCache.get(elt).deepCopy();
    }
    if (elt.getKind() == ElementKind.PACKAGE) {
      return toAnnotatedType(elt.asType(), false);
    }
    AnnotatedTypeMirror type;

    // Because of a bug in Java 8, annotations on type parameters are not stored in elements, so get
    // explicit annotations from the tree. (This bug has been fixed in Java 9.)  Also, since
    // annotations computed by the AnnotatedTypeFactory are stored in the element, the annotations
    // have to be retrieved from the tree so that only explicit annotations are returned.
    Tree decl = declarationFromElement(elt);

    if (decl == null) {
      type = stubTypes.getAnnotatedTypeMirror(elt);
      if (type == null) {
        type = toAnnotatedType(elt.asType(), ElementUtils.isTypeDeclaration(elt));
        ElementAnnotationApplier.apply(type, elt, this);
      }
    } else if (decl instanceof ClassTree) {
      type = fromClass((ClassTree) decl);
    } else if (decl instanceof VariableTree) {
      type = fromMember(decl);
    } else if (decl instanceof MethodTree) {
      type = fromMember(decl);
    } else if (decl.getKind() == Tree.Kind.TYPE_PARAMETER) {
      type = fromTypeTree(decl);
    } else {
      throw new BugInCF(
          "AnnotatedTypeFactory.fromElement: cannot be here. decl: "
              + decl.getKind()
              + " elt: "
              + elt);
    }

    type = mergeAnnotationFileAnnosIntoType(type, elt, ajavaTypes);
    if (currentFileAjavaTypes != null) {
      type = mergeAnnotationFileAnnosIntoType(type, elt, currentFileAjavaTypes);
    }

    if (checker.hasOption("mergeStubsWithSource")) {
      if (debugStubParser) {
        System.out.printf("fromElement: mergeStubsIntoType(%s, %s)", type, elt);
      }
      type = mergeAnnotationFileAnnosIntoType(type, elt, stubTypes);
      if (debugStubParser) {
        System.out.printf(" => %s%n", type);
      }
    }
    // Caching is disabled if annotation files are being parsed, because calls to this
    // method before the annotation files are fully read can return incorrect results.
    if (shouldCache
        && !stubTypes.isParsing()
        && !ajavaTypes.isParsing()
        && (currentFileAjavaTypes == null || !currentFileAjavaTypes.isParsing())) {
      elementCache.put(elt, type.deepCopy());
    }
    return type;
  }

  /**
   * Returns an AnnotatedDeclaredType with explicit annotations from the ClassTree {@code tree}.
   *
   * @param tree the class declaration
   * @return AnnotatedDeclaredType with explicit annotations from {@code tree}
   */
  private AnnotatedDeclaredType fromClass(ClassTree tree) {
    return TypeFromTree.fromClassTree(this, tree);
  }

  /**
   * Creates an AnnotatedTypeMirror for a variable or method declaration tree. The
   * AnnotatedTypeMirror contains annotations explicitly written on the tree.
   *
   * <p>If a VariableTree is a parameter to a lambda, this method also adds annotations from the
   * declared type of the functional interface and the executable type of its method.
   *
   * <p>The returned AnnotatedTypeMirror also contains explicitly written annotations from any ajava
   * file and if {@code -AmergeStubsWithSource} is passed, it also merges any explicitly written
   * annotations from stub files.
   *
   * @param tree MethodTree or VariableTree
   * @return AnnotatedTypeMirror with explicit annotations from {@code tree}
   */
  private final AnnotatedTypeMirror fromMember(Tree tree) {
    if (!(tree instanceof MethodTree || tree instanceof VariableTree)) {
      throw new BugInCF(
          "AnnotatedTypeFactory.fromMember: not a method or variable declaration: " + tree);
    }
    if (shouldCache && fromMemberTreeCache.containsKey(tree)) {
      return fromMemberTreeCache.get(tree).deepCopy();
    }
    AnnotatedTypeMirror result = TypeFromTree.fromMember(this, tree);

    result = mergeAnnotationFileAnnosIntoType(result, tree, ajavaTypes);
    if (currentFileAjavaTypes != null) {
      result = mergeAnnotationFileAnnosIntoType(result, tree, currentFileAjavaTypes);
    }

    if (checker.hasOption("mergeStubsWithSource")) {
      if (debugStubParser) {
        System.out.printf("fromClass: mergeStubsIntoType(%s, %s)", result, tree);
      }
      result = mergeAnnotationFileAnnosIntoType(result, tree, stubTypes);
      if (debugStubParser) {
        System.out.printf(" => %s%n", result);
      }
    }

    if (shouldCache) {
      fromMemberTreeCache.put(tree, result.deepCopy());
    }

    return result;
  }

  /**
   * Merges types from annotation files for {@code tree} into {@code type} by taking the greatest
   * lower bound of the annotations in both.
   *
   * @param type the type to apply annotation file types to
   * @param tree the tree from which to read annotation file types
   * @param source storage for current annotation file annotations
   * @return the given type, side-effected to add the annotation file types
   */
  private AnnotatedTypeMirror mergeAnnotationFileAnnosIntoType(
      @Nullable AnnotatedTypeMirror type, Tree tree, AnnotationFileElementTypes source) {
    Element elt = TreeUtils.elementFromTree(tree);
    return mergeAnnotationFileAnnosIntoType(type, elt, source);
  }

  /**
   * A scanner used to combine annotations from two AnnotatedTypeMirrors. The scanner requires
   * {@link #qualHierarchy}, which is set in {@link #postInit()} rather than the construtor, so
   * lazily initialize this field before use.
   */
  private @MonotonicNonNull AnnotatedTypeCombiner annotatedTypeCombiner = null;

  /**
   * Merges types from annotation files for {@code elt} into {@code type} by taking the greatest
   * lower bound of the annotations in both.
   *
   * @param type the type to apply annotation file types to
   * @param elt the element from which to read annotation file types
   * @param source storage for current annotation file annotations
   * @return the type, side-effected to add the annotation file types
   */
  protected AnnotatedTypeMirror mergeAnnotationFileAnnosIntoType(
      @Nullable AnnotatedTypeMirror type, Element elt, AnnotationFileElementTypes source) {
    AnnotatedTypeMirror typeFromFile = source.getAnnotatedTypeMirror(elt);
    if (typeFromFile == null) {
      return type;
    }
    if (type == null) {
      return typeFromFile;
    }
    if (annotatedTypeCombiner == null) {
      annotatedTypeCombiner = new AnnotatedTypeCombiner(qualHierarchy);
    }
    // Must merge (rather than only take the annotation file type if it is a subtype) to support
    // WPI.
    annotatedTypeCombiner.visit(typeFromFile, type);
    return type;
  }

  /**
   * Creates an AnnotatedTypeMirror for an ExpressionTree. The AnnotatedTypeMirror contains explicit
   * annotations written on the expression and for some expressions, annotations from
   * sub-expressions that could have been explicitly written, defaulted, refined, or otherwise
   * computed. (Expression whose type include annotations from sub-expressions are: ArrayAccessTree,
   * ConditionalExpressionTree, IdentifierTree, MemberSelectTree, and MethodInvocationTree.)
   *
   * <p>For example, the AnnotatedTypeMirror returned for an array access expression is the fully
   * annotated type of the array component of the array being accessed.
   *
   * @param tree an expression
   * @return AnnotatedTypeMirror of the expressions either fully-annotated or partially annotated
   *     depending on the kind of expression
   * @see TypeFromExpressionVisitor
   */
  private AnnotatedTypeMirror fromExpression(ExpressionTree tree) {
    if (shouldCache && fromExpressionTreeCache.containsKey(tree)) {
      return fromExpressionTreeCache.get(tree).deepCopy();
    }

    AnnotatedTypeMirror result = TypeFromTree.fromExpression(this, tree);

    if (shouldCache
        && tree.getKind() != Tree.Kind.NEW_CLASS
        && tree.getKind() != Kind.NEW_ARRAY
        && tree.getKind() != Kind.CONDITIONAL_EXPRESSION) {
      // Don't cache the type of some expressions, because incorrect annotations would be
      // cached during dataflow analysis. See Issue #602.
      fromExpressionTreeCache.put(tree, result.deepCopy());
    }
    return result;
  }

  /**
   * Creates an AnnotatedTypeMirror for the tree. The AnnotatedTypeMirror contains annotations
   * explicitly written on the tree. It also adds type arguments to raw types that include
   * annotations from the element declaration of the type {@link #fromElement(Element)}.
   *
   * <p>Called on the following trees: AnnotatedTypeTree, ArrayTypeTree, ParameterizedTypeTree,
   * PrimitiveTypeTree, TypeParameterTree, WildcardTree, UnionType, IntersectionTypeTree, and
   * IdentifierTree, MemberSelectTree.
   *
   * @param tree the type tree
   * @return the (partially) annotated type of the type in the AST
   */
  /*package private*/ final AnnotatedTypeMirror fromTypeTree(Tree tree) {
    if (shouldCache && fromTypeTreeCache.containsKey(tree)) {
      return fromTypeTreeCache.get(tree).deepCopy();
    }

    AnnotatedTypeMirror result = TypeFromTree.fromTypeTree(this, tree);

    if (shouldCache) {
      fromTypeTreeCache.put(tree, result.deepCopy());
    }
    return result;
  }

  // **********************************************************************
  // Customization methods meant to be overridden by subclasses to include
  // defaulted annotations
  // **********************************************************************

  /**
   * Changes annotations on a type obtained from a {@link Tree}. By default, this method does
   * nothing. GenericAnnotatedTypeFactory uses this method to implement defaulting and inference
   * (flow-sensitive type refinement). Its subclasses usually override it only to customize default
   * annotations.
   *
   * <p>Subclasses that override this method should also override {@link
   * #addComputedTypeAnnotations(Element, AnnotatedTypeMirror)}.
   *
   * <p>In classes that extend {@link GenericAnnotatedTypeFactory}, override {@link
   * GenericAnnotatedTypeFactory#addComputedTypeAnnotations(Tree, AnnotatedTypeMirror, boolean)}
   * instead of this method.
   *
   * @param tree an AST node
   * @param type the type obtained from {@code tree}
   */
  protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) {
    // Pass.
  }

  /**
   * Changes annotations on a type obtained from an {@link Element}. By default, this method does
   * nothing. GenericAnnotatedTypeFactory uses this method to implement defaulting.
   *
   * <p>Subclasses that override this method should also override {@link
   * #addComputedTypeAnnotations(Tree, AnnotatedTypeMirror)}.
   *
   * @param elt an element
   * @param type the type obtained from {@code elt}
   */
  protected void addComputedTypeAnnotations(Element elt, AnnotatedTypeMirror type) {
    // Pass.
  }

  /**
   * Adds default annotations to {@code type}. This method should only be used in places where the
   * correct annotations cannot be computed because of uninferred type arguments. (See {@link
   * AnnotatedWildcardType#isUninferredTypeArgument()}.)
   *
   * @param type annotated type to which default annotations are added
   */
  public void addDefaultAnnotations(AnnotatedTypeMirror type) {
    // Pass.
  }

  /**
   * A callback method for the AnnotatedTypeFactory subtypes to customize directSupertypes().
   * Overriding methods should merely change the annotations on the supertypes, without adding or
   * removing new types.
   *
   * <p>The default provided implementation adds {@code type} annotations to {@code supertypes}.
   * This allows the {@code type} and its supertypes to have the qualifiers.
   *
   * @param type the type whose supertypes are desired
   * @param supertypes the supertypes as specified by the base AnnotatedTypeFactory
   */
  protected void postDirectSuperTypes(
      AnnotatedTypeMirror type, List<? extends AnnotatedTypeMirror> supertypes) {
    // Use the effective annotations here to get the correct annotations
    // for type variables and wildcards.
    Set<AnnotationMirror> annotations = type.getEffectiveAnnotations();
    for (AnnotatedTypeMirror supertype : supertypes) {
      if (!annotations.equals(supertype.getEffectiveAnnotations())) {
        supertype.clearAnnotations();
        // TODO: is this correct for type variables and wildcards?
        supertype.addAnnotations(annotations);
      }
    }
  }

  /**
   * A callback method for the AnnotatedTypeFactory subtypes to customize
   * AnnotatedTypes.asMemberOf(). Overriding methods should merely change the annotations on the
   * subtypes, without changing the types.
   *
   * @param type the annotated type of the element
   * @param owner the annotated type of the receiver of the accessing tree
   * @param element the element of the field or method
   */
  public void postAsMemberOf(AnnotatedTypeMirror type, AnnotatedTypeMirror owner, Element element) {
    if (element.getKind() == ElementKind.FIELD) {
      addAnnotationFromFieldInvariant(type, owner, (VariableElement) element);
    }
    addComputedTypeAnnotations(element, type);
  }

  /**
   * Adds the qualifier specified by a field invariant for {@code field} to {@code type}.
   *
   * @param type annotated type to which the annotation is added
   * @param accessedVia the annotated type of the receiver of the accessing tree. (Only used to get
   *     the type element of the underling type.)
   * @param field element representing the field
   */
  protected void addAnnotationFromFieldInvariant(
      AnnotatedTypeMirror type, AnnotatedTypeMirror accessedVia, VariableElement field) {
    TypeMirror declaringType = accessedVia.getUnderlyingType();
    // Find the first upper bound that isn't a wildcard or type variable
    while (declaringType.getKind() == TypeKind.WILDCARD
        || declaringType.getKind() == TypeKind.TYPEVAR) {
      if (declaringType.getKind() == TypeKind.WILDCARD) {
        declaringType = TypesUtils.wildUpperBound(declaringType, processingEnv);
      } else if (declaringType.getKind() == TypeKind.TYPEVAR) {
        declaringType = ((TypeVariable) declaringType).getUpperBound();
      }
    }
    TypeElement typeElement = TypesUtils.getTypeElement(declaringType);
    if (ElementUtils.enclosingTypeElement(field).equals(typeElement)) {
      // If the field is declared in the accessedVia class, then the field in the invariant
      // cannot be this field, even if the field has the same name.
      return;
    }

    FieldInvariants invariants = getFieldInvariants(typeElement);
    if (invariants == null) {
      return;
    }
    List<AnnotationMirror> invariantAnnos = invariants.getQualifiersFor(field.getSimpleName());
    type.replaceAnnotations(invariantAnnos);
  }

  /**
   * Returns the field invariants for the given class, as expressed by the user in {@link
   * FieldInvariant @FieldInvariant} method annotations.
   *
   * <p>Subclasses may implement their own field invariant annotations if {@link
   * FieldInvariant @FieldInvariant} is not expressive enough. They must override this method to
   * properly create AnnotationMirror and also override {@link
   * #getFieldInvariantDeclarationAnnotations()} to return their field invariants.
   *
   * @param element class for which to get invariants
   * @return field invariants for {@code element}
   */
  public FieldInvariants getFieldInvariants(TypeElement element) {
    if (element == null) {
      return null;
    }
    AnnotationMirror fieldInvarAnno = getDeclAnnotation(element, FieldInvariant.class);
    if (fieldInvarAnno == null) {
      return null;
    }
    List<String> fields =
        AnnotationUtils.getElementValueArray(
            fieldInvarAnno, fieldInvariantFieldElement, String.class);
    List<@CanonicalName Name> classes =
        AnnotationUtils.getElementValueClassNames(fieldInvarAnno, fieldInvariantQualifierElement);
    List<AnnotationMirror> qualifiers =
        CollectionsPlume.mapList(
            (Name name) ->
                // Calling AnnotationBuilder.fromName (which ignores elements/fields) is acceptable
                // because @FieldInvariant does not handle classes with elements/fields.
                AnnotationBuilder.fromName(elements, name),
            classes);
    if (qualifiers.size() == 1) {
      while (fields.size() > qualifiers.size()) {
        qualifiers.add(qualifiers.get(0));
      }
    }
    if (fields.size() != qualifiers.size()) {
      // The user wrote a malformed @FieldInvariant annotation, so just return a malformed
      // FieldInvariants object.  The BaseTypeVisitor will issue an error.
      return new FieldInvariants(fields, qualifiers);
    }

    // Only keep qualifiers that are supported by this checker.  (The other qualifiers cannot
    // be checked by this checker, so they must be ignored.)
    List<String> annotatedFields = new ArrayList<>();
    List<AnnotationMirror> supportedQualifiers = new ArrayList<>();
    for (int i = 0; i < fields.size(); i++) {
      if (isSupportedQualifier(qualifiers.get(i))) {
        annotatedFields.add(fields.get(i));
        supportedQualifiers.add(qualifiers.get(i));
      }
    }
    if (annotatedFields.isEmpty()) {
      return null;
    }

    return new FieldInvariants(annotatedFields, supportedQualifiers);
  }

  /**
   * Returns the AnnotationTree which is a use of one of the field invariant annotations (as
   * specified via {@link #getFieldInvariantDeclarationAnnotations()}. If one isn't found, null is
   * returned.
   *
   * @param annoTrees list of trees to search; the result is one of the list elements, or null
   * @return the AnnotationTree that is a use of one of the field invariant annotations, or null if
   *     one isn't found
   */
  public AnnotationTree getFieldInvariantAnnotationTree(List<? extends AnnotationTree> annoTrees) {
    List<AnnotationMirror> annos = TreeUtils.annotationsFromTypeAnnotationTrees(annoTrees);
    for (int i = 0; i < annos.size(); i++) {
      for (Class<? extends Annotation> clazz : getFieldInvariantDeclarationAnnotations()) {
        if (areSameByClass(annos.get(i), clazz)) {
          return annoTrees.get(i);
        }
      }
    }
    return null;
  }

  /** Returns the set of classes of field invariant annotations. */
  protected Set<Class<? extends Annotation>> getFieldInvariantDeclarationAnnotations() {
    return Collections.singleton(FieldInvariant.class);
  }

  /**
   * A callback method for the AnnotatedTypeFactory subtypes to customize
   * AnnotatedTypeMirror.substitute().
   *
   * @param varDecl a declaration of a type variable
   * @param varUse a use of the same type variable
   * @param value the new type to substitute in for the type variable
   */
  public void postTypeVarSubstitution(
      AnnotatedTypeVariable varDecl, AnnotatedTypeVariable varUse, AnnotatedTypeMirror value) {
    if (!varUse.getAnnotationsField().isEmpty()
        && !AnnotationUtils.areSame(varUse.getAnnotationsField(), varDecl.getAnnotationsField())) {
      value.replaceAnnotations(varUse.getAnnotationsField());
    }
  }

  /**
   * Adapt the upper bounds of the type variables of a class relative to the type instantiation. In
   * some type systems, the upper bounds depend on the instantiation of the class. For example, in
   * the Generic Universe Type system, consider a class declaration
   *
   * <pre>{@code   class C<X extends @Peer Object> }</pre>
   *
   * then the instantiation
   *
   * <pre>{@code   @Rep C<@Rep Object> }</pre>
   *
   * is legal. The upper bounds of class C have to be adapted by the main modifier.
   *
   * <p>An example of an adaptation follows. Suppose, I have a declaration:
   *
   * <pre>{@code  class MyClass<E extends List<E>>}</pre>
   *
   * And an instantiation:
   *
   * <pre>{@code  new MyClass<@NonNull String>()}</pre>
   *
   * <p>The upper bound of E adapted to the argument String, would be {@code List<@NonNull String>}
   * and the lower bound would be an AnnotatedNullType.
   *
   * <p>TODO: ensure that this method is consistently used instead of directly querying the type
   * variables.
   *
   * @param type the use of the type
   * @param element the corresponding element
   * @return the adapted bounds of the type parameters
   */
  public List<AnnotatedTypeParameterBounds> typeVariablesFromUse(
      AnnotatedDeclaredType type, TypeElement element) {

    AnnotatedDeclaredType generic = getAnnotatedType(element);
    List<AnnotatedTypeMirror> targs = type.getTypeArguments();
    List<AnnotatedTypeMirror> tvars = generic.getTypeArguments();

    assert targs.size() == tvars.size()
        : "Mismatch in type argument size between " + type + " and " + generic;

    // System.err.printf("TVFU%n  type: %s%n  generic: %s%n", type, generic);

    Map<TypeVariable, AnnotatedTypeMirror> mapping = new HashMap<>();

    AnnotatedDeclaredType enclosing = type;
    while (enclosing != null) {
      List<AnnotatedTypeMirror> enclosingTArgs = enclosing.getTypeArguments();
      AnnotatedDeclaredType declaredType =
          getAnnotatedType((TypeElement) enclosing.getUnderlyingType().asElement());
      List<AnnotatedTypeMirror> enclosingTVars = declaredType.getTypeArguments();
      for (int i = 0; i < enclosingTArgs.size(); i++) {
        AnnotatedTypeVariable enclosingTVar = (AnnotatedTypeVariable) enclosingTVars.get(i);
        mapping.put(enclosingTVar.getUnderlyingType(), enclosingTArgs.get(i));
      }
      enclosing = enclosing.getEnclosingType();
    }

    List<AnnotatedTypeParameterBounds> res = new ArrayList<>(tvars.size());

    for (AnnotatedTypeMirror atm : tvars) {
      AnnotatedTypeVariable atv = (AnnotatedTypeVariable) atm;
      AnnotatedTypeMirror upper = typeVarSubstitutor.substitute(mapping, atv.getUpperBound());
      AnnotatedTypeMirror lower = typeVarSubstitutor.substitute(mapping, atv.getLowerBound());
      res.add(new AnnotatedTypeParameterBounds(upper, lower));
    }
    return res;
  }

  /**
   * Creates and returns an AnnotatedNullType qualified with {@code annotations}.
   *
   * @param annotations set of AnnotationMirrors to qualify the returned type with
   * @return AnnotatedNullType qualified with {@code annotations}
   */
  public AnnotatedNullType getAnnotatedNullType(Set<? extends AnnotationMirror> annotations) {
    final AnnotatedTypeMirror.AnnotatedNullType nullType =
        (AnnotatedNullType) toAnnotatedType(processingEnv.getTypeUtils().getNullType(), false);
    nullType.addAnnotations(annotations);
    return nullType;
  }

  // **********************************************************************
  // Utilities method for getting specific types from trees or elements
  // **********************************************************************

  /**
   * Return the implicit receiver type of an expression tree.
   *
   * <p>The result is null for expressions that don't have a receiver, e.g. for a local variable or
   * method parameter access. The result is also null for expressions that have an explicit
   * receiver.
   *
   * <p>Clients should generally call {@link #getReceiverType}.
   *
   * @param tree the expression that might have an implicit receiver
   * @return the type of the implicit receiver
   */
  protected @Nullable AnnotatedDeclaredType getImplicitReceiverType(ExpressionTree tree) {
    assert (tree.getKind() == Tree.Kind.IDENTIFIER
            || tree.getKind() == Tree.Kind.MEMBER_SELECT
            || tree.getKind() == Tree.Kind.METHOD_INVOCATION
            || tree.getKind() == Tree.Kind.NEW_CLASS)
        : "Unexpected tree kind: " + tree.getKind();

    // Return null if the element kind has no receiver.
    Element element = TreeUtils.elementFromTree(tree);
    assert element != null : "Unexpected null element for tree: " + tree;
    if (!ElementUtils.hasReceiver(element)) {
      return null;
    }

    // Return null if the receiver is explicit.
    if (TreeUtils.getReceiverTree(tree) != null) {
      return null;
    }

    TypeElement elementOfImplicitReceiver = ElementUtils.enclosingTypeElement(element);
    if (tree.getKind() == Kind.NEW_CLASS) {
      if (elementOfImplicitReceiver.getEnclosingElement() != null) {
        elementOfImplicitReceiver =
            ElementUtils.enclosingTypeElement(elementOfImplicitReceiver.getEnclosingElement());
      } else {
        elementOfImplicitReceiver = null;
      }
      if (elementOfImplicitReceiver == null) {
        // If the typeElt does not have an enclosing class, then the NewClassTree
        // does not have an implicit receiver.
        return null;
      }
    }

    TypeMirror typeOfImplicitReceiver = elementOfImplicitReceiver.asType();
    AnnotatedDeclaredType thisType = getSelfType(tree);
    if (thisType == null) {
      return null;
    }
    // An implicit receiver is the first enclosing type that is a subtype of the type where
    // element is declared.
    while (!isSubtype(thisType.getUnderlyingType(), typeOfImplicitReceiver)) {
      thisType = thisType.getEnclosingType();
    }
    return thisType;
  }

  /**
   * Returns the type of {@code this} at the location of {@code tree}. Returns {@code null} if
   * {@code tree} is in a location where {@code this} has no meaning, such as the body of a static
   * method.
   *
   * <p>The parameter is an arbitrary tree and does not have to mention "this", neither explicitly
   * nor implicitly. This method can be overridden for type-system specific behavior.
   *
   * @param tree location used to decide the type of {@code this}
   * @return the type of {@code this} at the location of {@code tree}
   */
  public @Nullable AnnotatedDeclaredType getSelfType(Tree tree) {
    if (TreeUtils.isClassTree(tree)) {
      return getAnnotatedType(TreeUtils.elementFromDeclaration((ClassTree) tree));
    }

    Tree enclosingTree = getEnclosingClassOrMethod(tree);
    if (enclosingTree == null) {
      // tree is inside an annotation, where "this" is not allowed. So, no self type exists.
      return null;
    } else if (enclosingTree.getKind() == Kind.METHOD) {
      MethodTree enclosingMethod = (MethodTree) enclosingTree;
      if (TreeUtils.isConstructor(enclosingMethod)) {
        return (AnnotatedDeclaredType) getAnnotatedType(enclosingMethod).getReturnType();
      } else {
        return getAnnotatedType(enclosingMethod).getReceiverType();
      }
    } else if (TreeUtils.isClassTree(enclosingTree)) {
      return (AnnotatedDeclaredType) getAnnotatedType(enclosingTree);
    }
    return null;
  }

  /** A set containing class, method, and annotation tree kinds. */
  private static final Set<Tree.Kind> classMethodAnnotationKinds =
      EnumSet.copyOf(TreeUtils.classTreeKinds());

  static {
    classMethodAnnotationKinds.add(Kind.METHOD);
    classMethodAnnotationKinds.add(Kind.TYPE_ANNOTATION);
    classMethodAnnotationKinds.add(Kind.ANNOTATION);
  }

  /**
   * Returns the innermost enclosing method or class tree of {@code tree}. If {@code tree} is
   * artificial (that is, created by dataflow), then {@link #artificialTreeToEnclosingElementMap} is
   * used to find the enclosing tree.
   *
   * <p>If the tree is inside an annotation, then {@code null} is returned.
   *
   * @param tree tree to whose innermost enclosing method or class to return
   * @return the innermost enclosing method or class tree of {@code tree}, or {@code null} if {@code
   *     tree} is inside an annotation
   */
  public @Nullable Tree getEnclosingClassOrMethod(Tree tree) {
    TreePath path = getPath(tree);
    Tree enclosing = TreePathUtil.enclosingOfKind(path, classMethodAnnotationKinds);
    if (enclosing != null) {
      if (enclosing.getKind() == Kind.ANNOTATION || enclosing.getKind() == Kind.TYPE_ANNOTATION) {
        return null;
      }
      return enclosing;
    }
    Element e = getEnclosingElementForArtificialTree(tree);
    if (e != null) {
      Element enclosingMethodOrClass = e;
      while (enclosingMethodOrClass != null
          && enclosingMethodOrClass.getKind() != ElementKind.METHOD
          && !enclosingMethodOrClass.getKind().isClass()
          && !enclosingMethodOrClass.getKind().isInterface()) {
        enclosingMethodOrClass = enclosingMethodOrClass.getEnclosingElement();
      }
      return declarationFromElement(enclosingMethodOrClass);
    }
    return getCurrentClassTree(tree);
  }

  /**
   * Returns the {@link AnnotatedTypeMirror} of the enclosing type at the location of {@code tree}
   * that is the same type as {@code typeElement}.
   *
   * @param typeElement type of the enclosing type to return
   * @param tree location to use
   * @return the enclosing type at the location of {@code tree} that is the same type as {@code
   *     typeElement}
   */
  public AnnotatedDeclaredType getEnclosingType(TypeElement typeElement, Tree tree) {
    AnnotatedDeclaredType thisType = getSelfType(tree);
    while (!isSameType(thisType.getUnderlyingType(), typeElement.asType())) {
      thisType = thisType.getEnclosingType();
    }
    return thisType;
  }

  /**
   * Returns true if the erasure of {@code type1} is a subtype of the erasure of {@code type2}.
   *
   * @param type1 a type
   * @param type2 a type
   * @return true if the erasure of {@code type1} is a subtype of the erasure of {@code type2}
   */
  private boolean isSubtype(TypeMirror type1, TypeMirror type2) {
    return types.isSubtype(types.erasure(type1), types.erasure(type2));
  }

  /**
   * Returns true if the erasure of {@code type1} is the same type as the erasure of {@code type2}.
   *
   * @param type1 a type
   * @param type2 a type
   * @return true if the erasure of {@code type1} is the same type as the erasure of {@code type2}
   */
  private boolean isSameType(TypeMirror type1, TypeMirror type2) {
    return types.isSameType(types.erasure(type1), types.erasure(type2));
  }

  /**
   * Returns the receiver type of the expression tree, which might be the type of an implicit {@code
   * this}. Returns null if the expression has no explicit or implicit receiver.
   *
   * @param expression the expression for which to determine the receiver type
   * @return the type of the receiver of expression
   */
  public final AnnotatedTypeMirror getReceiverType(ExpressionTree expression) {
    ExpressionTree receiver = TreeUtils.getReceiverTree(expression);
    if (receiver != null) {
      return getAnnotatedType(receiver);
    }

    Element element = TreeUtils.elementFromUse(expression);
    if (element != null && ElementUtils.hasReceiver(element)) {
      // The tree references an element that has a receiver, but the tree does not have an explicit
      // receiver. So, the tree must have an implicit receiver of "this" or "Outer.this".
      return getImplicitReceiverType(expression);
    } else {
      return null;
    }
  }

  /** The type for an instantiated generic method or constructor. */
  public static class ParameterizedExecutableType {
    /** The method's/constructor's type. */
    public final AnnotatedExecutableType executableType;
    /** The types of the generic type arguments. */
    public final List<AnnotatedTypeMirror> typeArgs;
    /** Create a ParameterizedExecutableType. */
    public ParameterizedExecutableType(
        AnnotatedExecutableType executableType, List<AnnotatedTypeMirror> typeArgs) {
      this.executableType = executableType;
      this.typeArgs = typeArgs;
    }

    @Override
    public String toString() {
      if (typeArgs.isEmpty()) {
        return executableType.toString();
      } else {
        StringJoiner typeArgsString = new StringJoiner(",", "<", ">");
        for (AnnotatedTypeMirror atm : typeArgs) {
          typeArgsString.add(atm.toString());
        }
        return typeArgsString + " " + executableType.toString();
      }
    }
  }

  /**
   * Determines the type of the invoked method based on the passed method invocation tree.
   *
   * <p>The returned method type has all type variables resolved, whether based on receiver type,
   * passed type parameters if any, and method invocation parameter.
   *
   * <p>Subclasses may override this method to customize inference of types or qualifiers based on
   * method invocation parameters.
   *
   * <p>As an implementation detail, this method depends on {@link AnnotatedTypes#asMemberOf(Types,
   * AnnotatedTypeFactory, AnnotatedTypeMirror, Element)}, and customization based on receiver type
   * should be in accordance to its specification.
   *
   * <p>The return type is a pair of the type of the invoked method and the (inferred) type
   * arguments. Note that neither the explicitly passed nor the inferred type arguments are
   * guaranteed to be subtypes of the corresponding upper bounds. See method {@link
   * org.checkerframework.common.basetype.BaseTypeVisitor#checkTypeArguments} for the checks of type
   * argument well-formedness.
   *
   * <p>Note that "this" and "super" constructor invocations are also handled by this method
   * (explicit or implicit ones, at the beginning of a constructor). Method {@link
   * #constructorFromUse(NewClassTree)} is only used for a constructor invocation in a "new"
   * expression.
   *
   * @param tree the method invocation tree
   * @return the method type being invoked with tree and the (inferred) type arguments
   */
  public ParameterizedExecutableType methodFromUse(MethodInvocationTree tree) {
    ExecutableElement methodElt = TreeUtils.elementFromUse(tree);
    AnnotatedTypeMirror receiverType = getReceiverType(tree);
    if (receiverType == null && TreeUtils.isSuperConstructorCall(tree)) {
      // super() calls don't have a receiver, but they should be view-point adapted as if
      // "this" is the receiver.
      receiverType = getSelfType(tree);
    }

    ParameterizedExecutableType result = methodFromUse(tree, methodElt, receiverType);
    if (checker.shouldResolveReflection()
        && reflectionResolver.isReflectiveMethodInvocation(tree)) {
      result = reflectionResolver.resolveReflectiveCall(this, tree, result);
    }

    AnnotatedExecutableType method = result.executableType;
    if (method.getReturnType().getKind() == TypeKind.WILDCARD
        && ((AnnotatedWildcardType) method.getReturnType()).isUninferredTypeArgument()) {
      // Get the correct Java type from the tree and use it as the upper bound of the wildcard.
      TypeMirror tm = TreeUtils.typeOf(tree);
      AnnotatedTypeMirror t = toAnnotatedType(tm, false);

      AnnotatedWildcardType wildcard = (AnnotatedWildcardType) method.getReturnType();
      if (ignoreUninferredTypeArguments) {
        // Remove the annotations so that default annotations are used instead.
        // (See call to addDefaultAnnotations below.)
        t.clearAnnotations();
      } else {
        t.replaceAnnotations(wildcard.getExtendsBound().getAnnotations());
      }
      wildcard.setExtendsBound(t);
      addDefaultAnnotations(wildcard);
    }

    return result;
  }

  /**
   * Determines the type of the invoked method based on the passed expression tree, executable
   * element, and receiver type.
   *
   * @param tree either a MethodInvocationTree or a MemberReferenceTree
   * @param methodElt the element of the referenced method
   * @param receiverType the type of the receiver
   * @return the method type being invoked with tree and the (inferred) type arguments
   * @see #methodFromUse(MethodInvocationTree)
   */
  public ParameterizedExecutableType methodFromUse(
      ExpressionTree tree, ExecutableElement methodElt, AnnotatedTypeMirror receiverType) {

    AnnotatedExecutableType memberTypeWithoutOverrides =
        getAnnotatedType(methodElt); // get unsubstituted type
    AnnotatedExecutableType memberTypeWithOverrides =
        (AnnotatedExecutableType)
            applyFakeOverrides(receiverType, methodElt, memberTypeWithoutOverrides);
    methodFromUsePreSubstitution(tree, memberTypeWithOverrides);

    AnnotatedExecutableType methodType =
        AnnotatedTypes.asMemberOf(types, this, receiverType, methodElt, memberTypeWithOverrides);
    List<AnnotatedTypeMirror> typeargs = new ArrayList<>(methodType.getTypeVariables().size());

    Map<TypeVariable, AnnotatedTypeMirror> typeVarMapping =
        AnnotatedTypes.findTypeArguments(processingEnv, this, tree, methodElt, methodType);

    if (!typeVarMapping.isEmpty()) {
      for (AnnotatedTypeVariable tv : methodType.getTypeVariables()) {
        if (typeVarMapping.get(tv.getUnderlyingType()) == null) {
          throw new BugInCF(
              "AnnotatedTypeFactory.methodFromUse:mismatch between declared method type variables"
                  + " and the inferred method type arguments. Method type variables: "
                  + methodType.getTypeVariables()
                  + "; "
                  + "Inferred method type arguments: "
                  + typeVarMapping);
        }
        typeargs.add(typeVarMapping.get(tv.getUnderlyingType()));
      }
      methodType =
          (AnnotatedExecutableType) typeVarSubstitutor.substitute(typeVarMapping, methodType);
    }

    if (tree.getKind() == Tree.Kind.METHOD_INVOCATION
        && TreeUtils.isMethodInvocation(tree, objectGetClass, processingEnv)) {
      adaptGetClassReturnTypeToReceiver(methodType, receiverType);
    }

    return new ParameterizedExecutableType(methodType, typeargs);
  }

  /**
   * Given a member and its type, returns the type with fake overrides applied to it.
   *
   * @param receiverType the type of the class that contains member (or a subtype of it)
   * @param member a type member, such as a method or field
   * @param memberType the type of {@code member}
   * @return {@code memberType}, adjusted according to fake overrides
   */
  private AnnotatedTypeMirror applyFakeOverrides(
      AnnotatedTypeMirror receiverType, Element member, AnnotatedTypeMirror memberType) {
    // Currently, handle only methods, not fields.  TODO: Handle fields.
    if (memberType.getKind() != TypeKind.EXECUTABLE) {
      return memberType;
    }

    AnnotationFileElementTypes afet = stubTypes;
    AnnotatedExecutableType methodType =
        (AnnotatedExecutableType) afet.getFakeOverride(member, receiverType);
    if (methodType == null) {
      methodType = (AnnotatedExecutableType) memberType;
    }
    return methodType;
  }

  /**
   * A callback method for the AnnotatedTypeFactory subtypes to customize the handling of the
   * declared method type before type variable substitution.
   *
   * @param tree either a method invocation or a member reference tree
   * @param type declared method type before type variable substitution
   */
  protected void methodFromUsePreSubstitution(ExpressionTree tree, AnnotatedExecutableType type) {
    assert tree instanceof MethodInvocationTree || tree instanceof MemberReferenceTree;
  }

  /**
   * Java special-cases the return type of {@link java.lang.Class#getClass() getClass()}. Though the
   * method has a return type of {@code Class<?>}, the compiler special cases this return-type and
   * changes the bound of the type argument to the erasure of the receiver type. For example:
   *
   * <ul>
   *   <li>{@code x.getClass()} has the type {@code Class< ? extends erasure_of_x >}
   *   <li>{@code someInteger.getClass()} has the type {@code Class< ? extends Integer >}
   * </ul>
   *
   * @param getClassType this must be a type representing a call to Object.getClass otherwise a
   *     runtime exception will be thrown. It is modified by side effect.
   * @param receiverType the receiver type of the method invocation (not the declared receiver type)
   */
  protected void adaptGetClassReturnTypeToReceiver(
      final AnnotatedExecutableType getClassType, final AnnotatedTypeMirror receiverType) {
    // TODO: should the receiver type ever be a declaration??
    // Work on removing the asUse() call.
    final AnnotatedTypeMirror newBound = receiverType.getErased().asUse();

    final AnnotatedTypeMirror returnType = getClassType.getReturnType();
    if (returnType == null
        || !(returnType.getKind() == TypeKind.DECLARED)
        || ((AnnotatedDeclaredType) returnType).getTypeArguments().size() != 1) {
      throw new BugInCF(
          "Unexpected type passed to AnnotatedTypes.adaptGetClassReturnTypeToReceiver%n"
              + "getClassType=%s%nreceiverType=%s",
          getClassType, receiverType);
    }

    final AnnotatedDeclaredType returnAdt = (AnnotatedDeclaredType) getClassType.getReturnType();
    final List<AnnotatedTypeMirror> typeArgs = returnAdt.getTypeArguments();

    // Usually, the only locations that will add annotations to the return type are getClass in stub
    // files defaults and propagation tree annotator.  Since getClass is final they cannot come from
    // source code.  Also, since the newBound is an erased type we have no type arguments.  So, we
    // just copy the annotations from the bound of the declared type to the new bound.
    final AnnotatedWildcardType classWildcardArg = (AnnotatedWildcardType) typeArgs.get(0);
    Set<AnnotationMirror> newAnnos = AnnotationUtils.createAnnotationSet();
    Set<AnnotationMirror> typeBoundAnnos = getTypeDeclarationBounds(newBound.getUnderlyingType());
    Set<AnnotationMirror> wildcardBoundAnnos = classWildcardArg.getExtendsBound().getAnnotations();
    for (AnnotationMirror typeBoundAnno : typeBoundAnnos) {
      AnnotationMirror wildcardAnno =
          qualHierarchy.findAnnotationInSameHierarchy(wildcardBoundAnnos, typeBoundAnno);
      if (qualHierarchy.isSubtype(typeBoundAnno, wildcardAnno)) {
        newAnnos.add(typeBoundAnno);
      } else {
        newAnnos.add(wildcardAnno);
      }
    }
    newBound.replaceAnnotations(newAnnos);

    classWildcardArg.setExtendsBound(newBound);
  }

  /**
   * Return the element type of {@code expression}. This is usually the type of {@code
   * expression.itertor().next()}. If {@code expression} is an array, it is the component type of
   * the array.
   *
   * @param expression an expression whose type is an array or implements {@link Iterable}
   * @return the type of {@code expression.itertor().next()} or if {@code expression} is an array,
   *     the component type of the array.
   */
  public AnnotatedTypeMirror getIterableElementType(ExpressionTree expression) {
    return getIterableElementType(expression, getAnnotatedType(expression));
  }

  /**
   * Return the element type of {@code iterableType}. This is usually the type of {@code
   * expression.itertor().next()}. If {@code expression} is an array, it is the component type of
   * the array.
   *
   * @param expression an expression whose type is an array or implements {@link Iterable}
   * @param iterableType the type of the expression
   * @return the type of {@code expression.itertor().next()} or if {@code expression} is an array,
   *     the component type of the array.
   */
  protected AnnotatedTypeMirror getIterableElementType(
      ExpressionTree expression, AnnotatedTypeMirror iterableType) {
    switch (iterableType.getKind()) {
      case ARRAY:
        return ((AnnotatedArrayType) iterableType).getComponentType();
      case WILDCARD:
        return getIterableElementType(
            expression, ((AnnotatedWildcardType) iterableType).getExtendsBound().deepCopy());
      case TYPEVAR:
        return getIterableElementType(
            expression, ((AnnotatedTypeVariable) iterableType).getUpperBound());
      case DECLARED:
        AnnotatedDeclaredType dt =
            AnnotatedTypes.asSuper(this, iterableType, this.iterableDeclType);
        if (dt.getTypeArguments().isEmpty()) {
          TypeElement e = ElementUtils.getTypeElement(processingEnv, Object.class);
          return getAnnotatedType(e);
        } else {
          return dt.getTypeArguments().get(0);
        }

        // TODO: Properly desugar Iterator.next(), which is needed if an annotated JDK has
        // annotations on Iterator#next.
        // The below doesn't work because methodFromUse() assumes that the expression tree
        // matches the method element.
        // TypeElement iteratorElement =
        //         ElementUtils.getTypeElement(processingEnv, Iterator.class);
        // AnnotatedTypeMirror iteratorType =
        //         AnnotatedTypeMirror.createType(iteratorElement.asType(), this, false);
        // Map<TypeVariable, AnnotatedTypeMirror> mapping = new HashMap<>();
        // mapping.put(
        //         (TypeVariable) iteratorElement.getTypeParameters().get(0).asType(),
        //          typeArg);
        // iteratorType = typeVarSubstitutor.substitute(mapping, iteratorType);
        // ExecutableElement next =
        //         TreeUtils.getMethod("java.util.Iterator", "next", 0, processingEnv);
        // ParameterizedExecutableType m = methodFromUse(expression, next, iteratorType);
        // return m.executableType.getReturnType();
      default:
        throw new BugInCF(
            "AnnotatedTypeFactory.getIterableElementType: not iterable type: " + iterableType);
    }
  }

  /**
   * Determines the type of the invoked constructor based on the passed new class tree.
   *
   * <p>The returned method type has all type variables resolved, whether based on receiver type,
   * passed type parameters if any, and constructor invocation parameter.
   *
   * <p>Subclasses may override this method to customize inference of types or qualifiers based on
   * constructor invocation parameters.
   *
   * <p>As an implementation detail, this method depends on {@link AnnotatedTypes#asMemberOf(Types,
   * AnnotatedTypeFactory, AnnotatedTypeMirror, Element)}, and customization based on receiver type
   * should be in accordance with its specification.
   *
   * <p>The return type is a pair of the type of the invoked constructor and the (inferred) type
   * arguments. Note that neither the explicitly passed nor the inferred type arguments are
   * guaranteed to be subtypes of the corresponding upper bounds. See method {@link
   * org.checkerframework.common.basetype.BaseTypeVisitor#checkTypeArguments} for the checks of type
   * argument well-formedness.
   *
   * <p>Note that "this" and "super" constructor invocations are handled by method {@link
   * #methodFromUse}. This method only handles constructor invocations in a "new" expression.
   *
   * @param tree the constructor invocation tree
   * @return the annotated type of the invoked constructor (as an executable type) and the
   *     (inferred) type arguments
   */
  public ParameterizedExecutableType constructorFromUse(NewClassTree tree) {
    AnnotatedTypeMirror type = fromNewClass(tree);
    addComputedTypeAnnotations(tree, type);

    ExecutableElement ctor = TreeUtils.constructor(tree);
    AnnotatedExecutableType con = getAnnotatedType(ctor); // get unsubstituted type
    if (TreeUtils.hasSyntheticArgument(tree)) {
      AnnotatedExecutableType t =
          (AnnotatedExecutableType) getAnnotatedType(((JCNewClass) tree).constructor);
      List<AnnotatedTypeMirror> p = new ArrayList<>(con.getParameterTypes().size() + 1);
      p.add(t.getParameterTypes().get(0));
      p.addAll(1, con.getParameterTypes());
      t.setParameterTypes(p);
      con = t;
    }

    constructorFromUsePreSubstitution(tree, con);

    con = AnnotatedTypes.asMemberOf(types, this, type, ctor, con);

    Map<TypeVariable, AnnotatedTypeMirror> typeVarMapping =
        AnnotatedTypes.findTypeArguments(processingEnv, this, tree, ctor, con);

    List<AnnotatedTypeMirror> typeargs = new ArrayList<>(con.getTypeVariables().size());
    if (typeVarMapping.isEmpty()) {
      typeargs = Collections.emptyList();
    } else {
      typeargs =
          CollectionsPlume.mapList(
              (AnnotatedTypeVariable tv) -> typeVarMapping.get(tv.getUnderlyingType()),
              con.getTypeVariables());
      con = (AnnotatedExecutableType) typeVarSubstitutor.substitute(typeVarMapping, con);
    }

    return new ParameterizedExecutableType(con, typeargs);
  }

  /**
   * A callback method for the AnnotatedTypeFactory subtypes to customize the handling of the
   * declared constructor type before type variable substitution.
   *
   * @param tree a NewClassTree from constructorFromUse()
   * @param type declared method type before type variable substitution
   */
  protected void constructorFromUsePreSubstitution(
      NewClassTree tree, AnnotatedExecutableType type) {}

  /**
   * Returns the return type of the method {@code m}.
   *
   * @param m tree of a method declaration
   * @return the return type of the method
   */
  public AnnotatedTypeMirror getMethodReturnType(MethodTree m) {
    AnnotatedExecutableType methodType = getAnnotatedType(m);
    AnnotatedTypeMirror ret = methodType.getReturnType();
    return ret;
  }

  /**
   * Returns the return type of the method {@code m} at the return statement {@code r}. This
   * implementation just calls {@link #getMethodReturnType(MethodTree)}, but subclasses may override
   * this method to change the type based on the return statement.
   *
   * @param m tree of a method declaration
   * @param r a return statement within method {@code m}
   * @return the return type of the method {@code m} at the return statement {@code r}
   */
  public AnnotatedTypeMirror getMethodReturnType(MethodTree m, ReturnTree r) {
    return getMethodReturnType(m);
  }

  /**
   * Creates an AnnotatedDeclaredType for a NewClassTree. Only adds explicit annotations, unless
   * newClassTree has a diamond operator. In that case, the annotations on the type arguments are
   * inferred using the assignment context and contain defaults.
   *
   * <p>Also, fully annotates the enclosing type of the returned declared type.
   *
   * <p>(Subclass beside {@link GenericAnnotatedTypeFactory} should not override this method.)
   *
   * @param newClassTree NewClassTree
   * @return AnnotatedDeclaredType
   */
  public AnnotatedDeclaredType fromNewClass(NewClassTree newClassTree) {

    AnnotatedDeclaredType enclosingType = (AnnotatedDeclaredType) getReceiverType(newClassTree);

    // Diamond trees that are not anonymous classes.
    if (TreeUtils.isDiamondTree(newClassTree) && newClassTree.getClassBody() == null) {
      AnnotatedDeclaredType type =
          (AnnotatedDeclaredType) toAnnotatedType(TreeUtils.typeOf(newClassTree), false);
      if (((com.sun.tools.javac.code.Type) type.underlyingType)
          .tsym
          .getTypeParameters()
          .nonEmpty()) {
        Pair<Tree, AnnotatedTypeMirror> ctx = this.visitorState.getAssignmentContext();
        if (ctx != null) {
          AnnotatedTypeMirror ctxtype = ctx.second;
          fromNewClassContextHelper(type, ctxtype);
        } else {
          TreePath p = getPath(newClassTree);
          AnnotatedTypeMirror ctxtype = TypeArgInferenceUtil.assignedTo(this, p);
          if (ctxtype != null) {
            fromNewClassContextHelper(type, ctxtype);
          } else {
            // give up trying and set to raw.
            type.setWasRaw();
          }
        }
      }
      AnnotatedDeclaredType fromTypeTree =
          (AnnotatedDeclaredType) TypeFromTree.fromTypeTree(this, newClassTree.getIdentifier());
      type.replaceAnnotations(fromTypeTree.getAnnotations());
      type.setEnclosingType(enclosingType);
      return type;
    } else if (newClassTree.getClassBody() != null) {
      AnnotatedDeclaredType type =
          (AnnotatedDeclaredType) toAnnotatedType(TreeUtils.typeOf(newClassTree), false);
      // If newClassTree creates an anonymous class, then annotations in this location:
      //   new @HERE Class() {}
      // are on not on the identifier newClassTree, but rather on the modifier newClassTree.
      List<? extends AnnotationTree> annos =
          newClassTree.getClassBody().getModifiers().getAnnotations();
      type.addAnnotations(TreeUtils.annotationsFromTypeAnnotationTrees(annos));
      type.setEnclosingType(enclosingType);
      return type;
    } else {
      // If newClassTree does not create anonymous class,
      // newClassTree.getIdentifier includes the explicit annotations in this location:
      //   new @HERE Class()
      AnnotatedDeclaredType type =
          (AnnotatedDeclaredType) TypeFromTree.fromTypeTree(this, newClassTree.getIdentifier());
      type.setEnclosingType(enclosingType);
      return type;
    }
  }

  // This method extracts the ugly hacky parts.
  // This method should be rewritten and in particular diamonds should be
  // implemented cleanly.
  // See Issue 289.
  private void fromNewClassContextHelper(AnnotatedDeclaredType type, AnnotatedTypeMirror ctxtype) {
    switch (ctxtype.getKind()) {
      case DECLARED:
        AnnotatedDeclaredType adctx = (AnnotatedDeclaredType) ctxtype;

        if (type.getTypeArguments().size() == adctx.getTypeArguments().size()) {
          // Try to simply take the type arguments from LHS.
          List<AnnotatedTypeMirror> oldArgs = type.getTypeArguments();
          List<AnnotatedTypeMirror> newArgs = adctx.getTypeArguments();
          for (int i = 0; i < type.getTypeArguments().size(); ++i) {
            if (!types.isSubtype(newArgs.get(i).underlyingType, oldArgs.get(i).underlyingType)) {
              // One of the underlying types doesn't match. Give up.
              return;
            }
          }

          type.setTypeArguments(newArgs);

          /* It would be nice to call isSubtype for a basic sanity check.
           * However, the type might not have been completely initialized yet,
           * so isSubtype might fail.
           *
          if (!typeHierarchy.isSubtype(type, ctxtype)) {
              // Simply taking the newArgs didn't result in a valid subtype.
              // Give up and simply use the inferred types.
              type.setTypeArguments(oldArgs);
          }
          */
        } else {
          // TODO: Find a way to determine annotated type arguments.
          // Look at what Attr and Resolve are doing and rework this whole method.
        }
        break;

      case ARRAY:
        // This new class is in the initializer of an array.
        // The array being created can't have a generic component type, so nothing to be done.
        break;
      case TYPEVAR:
        // TODO: this should NOT be necessary.
        // org.checkerframework.dataflow.cfg.node.MethodAccessNode.MethodAccessNode(ExpressionTree,
        // Node)
        // Uses an ExecutableElement, which did not substitute type variables.
        break;
      case WILDCARD:
        // TODO: look at bounds of wildcard and see whether we can improve.
        break;
      default:
        if (ctxtype.getKind().isPrimitive()) {
          // See Issue 438. Ignore primitive types for diamond inference - a primitive
          // type is never a suitable context anyway.
        } else {
          throw new BugInCF(
              "AnnotatedTypeFactory.fromNewClassContextHelper: unexpected context: "
                  + ctxtype
                  + " ("
                  + ctxtype.getKind()
                  + ")");
        }
    }
  }

  /**
   * Returns the annotated boxed type of the given primitive type. The returned type would only have
   * the annotations on the given type.
   *
   * <p>Subclasses may override this method safely to override this behavior.
   *
   * @param type the primitive type
   * @return the boxed declared type of the passed primitive type
   */
  public AnnotatedDeclaredType getBoxedType(AnnotatedPrimitiveType type) {
    TypeElement typeElt = types.boxedClass(type.getUnderlyingType());
    AnnotatedDeclaredType dt = fromElement(typeElt);
    dt.addAnnotations(type.getAnnotations());
    return dt;
  }

  /**
   * Return a primitive type: either the argument, or the result of unboxing it (which might affect
   * its annotations).
   *
   * <p>Subclasses should override {@link #getUnboxedType} rather than this method.
   *
   * @param type a type: a primitive or boxed primitive
   * @return the unboxed variant of the type
   */
  public final AnnotatedPrimitiveType applyUnboxing(AnnotatedTypeMirror type) {
    TypeMirror underlying = type.getUnderlyingType();
    if (TypesUtils.isPrimitive(underlying)) {
      return (AnnotatedPrimitiveType) type;
    } else if (TypesUtils.isBoxedPrimitive(underlying)) {
      return getUnboxedType((AnnotatedDeclaredType) type);
    } else {
      throw new BugInCF("Bad argument to applyUnboxing: " + type);
    }
  }

  /**
   * Returns the annotated primitive type of the given declared type if it is a boxed declared type.
   * Otherwise, it throws <i>IllegalArgumentException</i> exception.
   *
   * <p>In the {@code AnnotatedTypeFactory} implementation, the returned type has the same primary
   * annotations as the given type. Subclasses may override this behavior.
   *
   * @param type the declared type
   * @return the unboxed primitive type
   * @throws IllegalArgumentException if the type given has no unbox conversion
   */
  public AnnotatedPrimitiveType getUnboxedType(AnnotatedDeclaredType type)
      throws IllegalArgumentException {
    PrimitiveType primitiveType = types.unboxedType(type.getUnderlyingType());
    AnnotatedPrimitiveType pt =
        (AnnotatedPrimitiveType) AnnotatedTypeMirror.createType(primitiveType, this, false);
    pt.addAnnotations(type.getAnnotations());
    return pt;
  }

  /**
   * Returns AnnotatedDeclaredType with underlying type String and annotations copied from type.
   * Subclasses may change the annotations.
   *
   * @param type type to convert to String
   * @return AnnotatedTypeMirror that results from converting type to a String type
   */
  // TODO: Test that this is called in all the correct locations
  // See Issue #715
  // https://github.com/typetools/checker-framework/issues/715
  public AnnotatedDeclaredType getStringType(AnnotatedTypeMirror type) {
    TypeMirror stringTypeMirror = TypesUtils.typeFromClass(String.class, types, elements);
    AnnotatedDeclaredType stringATM =
        (AnnotatedDeclaredType)
            AnnotatedTypeMirror.createType(stringTypeMirror, this, type.isDeclaration());
    stringATM.addAnnotations(type.getEffectiveAnnotations());
    return stringATM;
  }

  /**
   * Returns a widened type if applicable, otherwise returns its first argument.
   *
   * <p>Subclasses should override {@link #getWidenedAnnotations} rather than this method.
   *
   * @param exprType type to possibly widen
   * @param widenedType type to possibly widen to; its annotations are ignored
   * @return if widening is applicable, the result of converting {@code type} to the underlying type
   *     of {@code widenedType}; otherwise {@code type}
   */
  public final AnnotatedTypeMirror getWidenedType(
      AnnotatedTypeMirror exprType, AnnotatedTypeMirror widenedType) {
    TypeKind exprKind = exprType.getKind();
    TypeKind widenedKind = widenedType.getKind();

    if (!TypeKindUtils.isNumeric(widenedKind)) {
      // The target type is not a numeric primitive, so primitive widening is not applicable.
      return exprType;
    }

    AnnotatedPrimitiveType exprPrimitiveType;
    if (TypeKindUtils.isNumeric(exprKind)) {
      exprPrimitiveType = (AnnotatedPrimitiveType) exprType;
    } else if (TypesUtils.isNumericBoxed(exprType.getUnderlyingType())) {
      exprPrimitiveType = getUnboxedType((AnnotatedDeclaredType) exprType);
    } else {
      return exprType;
    }

    switch (TypeKindUtils.getPrimitiveConversionKind(
        exprPrimitiveType.getKind(), widenedType.getKind())) {
      case WIDENING:
        return getWidenedPrimitive(exprPrimitiveType, widenedType.getUnderlyingType());
      case NARROWING:
        return getNarrowedPrimitive(exprPrimitiveType, widenedType.getUnderlyingType());
      case SAME:
        return exprType;
      default:
        throw new Error("unhandled PrimitiveConversionKind");
    }
  }

  /**
   * Applies widening if applicable, otherwise returns its first argument.
   *
   * <p>Subclasses should override {@link #getWidenedAnnotations} rather than this method.
   *
   * @param exprAnnos annotations to possibly widen
   * @param exprTypeMirror type to possibly widen
   * @param widenedType type to possibly widen to; its annotations are ignored
   * @return if widening is applicable, the result of converting {@code type} to the underlying type
   *     of {@code widenedType}; otherwise {@code type}
   */
  public final AnnotatedTypeMirror getWidenedType(
      Set<AnnotationMirror> exprAnnos, TypeMirror exprTypeMirror, AnnotatedTypeMirror widenedType) {
    AnnotatedTypeMirror exprType = toAnnotatedType(exprTypeMirror, false);
    exprType.replaceAnnotations(exprAnnos);
    return getWidenedType(exprType, widenedType);
  }

  /**
   * Returns an AnnotatedPrimitiveType with underlying type {@code widenedTypeMirror} and with
   * annotations copied or adapted from {@code type}.
   *
   * @param type type to widen; a primitive or boxed primitive
   * @param widenedTypeMirror underlying type for the returned type mirror; a primitive or boxed
   *     primitive (same boxing as {@code type})
   * @return result of converting {@code type} to {@code widenedTypeMirror}
   */
  private AnnotatedPrimitiveType getWidenedPrimitive(
      AnnotatedPrimitiveType type, TypeMirror widenedTypeMirror) {
    AnnotatedPrimitiveType result =
        (AnnotatedPrimitiveType)
            AnnotatedTypeMirror.createType(widenedTypeMirror, this, type.isDeclaration());
    result.addAnnotations(
        getWidenedAnnotations(type.getAnnotations(), type.getKind(), result.getKind()));
    return result;
  }

  /**
   * Returns annotations applicable to type {@code narrowedTypeKind}, that are copied or adapted
   * from {@code annos}.
   *
   * @param annos annotations to narrow, from a primitive or boxed primitive
   * @param typeKind primitive type to narrow
   * @param narrowedTypeKind target for the returned annotations; a primitive type that is narrower
   *     than {@code typeKind} (in the sense of JLS 5.1.3).
   * @return result of converting {@code annos} from {@code typeKind} to {@code narrowedTypeKind}
   */
  public Set<AnnotationMirror> getNarrowedAnnotations(
      Set<AnnotationMirror> annos, TypeKind typeKind, TypeKind narrowedTypeKind) {
    return annos;
  }

  /**
   * Returns annotations applicable to type {@code widenedTypeKind}, that are copied or adapted from
   * {@code annos}.
   *
   * @param annos annotations to widen, from a primitive or boxed primitive
   * @param typeKind primitive type to widen
   * @param widenedTypeKind target for the returned annotations; a primitive type that is wider than
   *     {@code typeKind} (in the sense of JLS 5.1.2)
   * @return result of converting {@code annos} from {@code typeKind} to {@code widenedTypeKind}
   */
  public Set<AnnotationMirror> getWidenedAnnotations(
      Set<AnnotationMirror> annos, TypeKind typeKind, TypeKind widenedTypeKind) {
    return annos;
  }

  /**
   * Returns the types of the two arguments to the BinaryTree, accounting for widening and unboxing
   * if applicable.
   *
   * @param node a binary tree
   * @return the types of the two arguments
   */
  public Pair<AnnotatedTypeMirror, AnnotatedTypeMirror> binaryTreeArgTypes(BinaryTree node) {
    return binaryTreeArgTypes(
        getAnnotatedType(node.getLeftOperand()), getAnnotatedType(node.getRightOperand()));
  }

  /**
   * Returns the types of the two arguments to the CompoundAssignmentTree, accounting for widening
   * and unboxing if applicable.
   *
   * @param node a compound assignment tree
   * @return the types of the two arguments
   */
  public Pair<AnnotatedTypeMirror, AnnotatedTypeMirror> compoundAssignmentTreeArgTypes(
      CompoundAssignmentTree node) {
    return binaryTreeArgTypes(
        getAnnotatedType(node.getVariable()), getAnnotatedType(node.getExpression()));
  }

  /**
   * Returns the types of the two arguments to a binarya operation, accounting for widening and
   * unboxing if applicable.
   *
   * @param left the type of the left argument of a binary operation
   * @param right the type of the right argument of a binary operation
   * @return the types of the two arguments
   */
  public Pair<AnnotatedTypeMirror, AnnotatedTypeMirror> binaryTreeArgTypes(
      AnnotatedTypeMirror left, AnnotatedTypeMirror right) {
    TypeKind resultTypeKind =
        TypeKindUtils.widenedNumericType(left.getUnderlyingType(), right.getUnderlyingType());
    if (TypeKindUtils.isNumeric(resultTypeKind)) {
      TypeMirror resultTypeMirror = types.getPrimitiveType(resultTypeKind);
      AnnotatedPrimitiveType leftUnboxed = applyUnboxing(left);
      AnnotatedPrimitiveType rightUnboxed = applyUnboxing(right);
      AnnotatedPrimitiveType leftWidened =
          (leftUnboxed.getKind() == resultTypeKind
              ? leftUnboxed
              : getWidenedPrimitive(leftUnboxed, resultTypeMirror));
      AnnotatedPrimitiveType rightWidened =
          (rightUnboxed.getKind() == resultTypeKind
              ? rightUnboxed
              : getWidenedPrimitive(rightUnboxed, resultTypeMirror));
      return Pair.of(leftWidened, rightWidened);
    } else {
      return Pair.of(left, right);
    }
  }

  /**
   * Returns AnnotatedPrimitiveType with underlying type {@code narrowedTypeMirror} and with
   * annotations copied or adapted from {@code type}.
   *
   * <p>Currently this method is called only for primitives that are narrowed at assignments from
   * literal ints, for example, {@code byte b = 1;}. All other narrowing conversions happen at
   * typecasts.
   *
   * @param type type to narrow
   * @param narrowedTypeMirror underlying type for the returned type mirror
   * @return result of converting {@code type} to {@code narrowedTypeMirror}
   */
  public AnnotatedPrimitiveType getNarrowedPrimitive(
      AnnotatedPrimitiveType type, TypeMirror narrowedTypeMirror) {
    AnnotatedPrimitiveType narrowed =
        (AnnotatedPrimitiveType)
            AnnotatedTypeMirror.createType(narrowedTypeMirror, this, type.isDeclaration());
    narrowed.addAnnotations(type.getAnnotations());
    return narrowed;
  }

  /**
   * Returns the VisitorState instance used by the factory to infer types.
   *
   * @return the VisitorState instance used by the factory to infer types
   */
  public VisitorState getVisitorState() {
    return this.visitorState;
  }

  // **********************************************************************
  // random methods wrapping #getAnnotatedType(Tree) and #fromElement(Tree)
  // with appropriate casts to reduce casts on the client side
  // **********************************************************************

  /**
   * See {@link #getAnnotatedType(Tree)}.
   *
   * @see #getAnnotatedType(Tree)
   */
  public final AnnotatedDeclaredType getAnnotatedType(ClassTree tree) {
    return (AnnotatedDeclaredType) getAnnotatedType((Tree) tree);
  }

  /**
   * See {@link #getAnnotatedType(Tree)}.
   *
   * @see #getAnnotatedType(Tree)
   */
  public final AnnotatedDeclaredType getAnnotatedType(NewClassTree tree) {
    return (AnnotatedDeclaredType) getAnnotatedType((Tree) tree);
  }

  /**
   * See {@link #getAnnotatedType(Tree)}.
   *
   * @see #getAnnotatedType(Tree)
   */
  public final AnnotatedArrayType getAnnotatedType(NewArrayTree tree) {
    return (AnnotatedArrayType) getAnnotatedType((Tree) tree);
  }

  /**
   * See {@link #getAnnotatedType(Tree)}.
   *
   * @see #getAnnotatedType(Tree)
   */
  public final AnnotatedExecutableType getAnnotatedType(MethodTree tree) {
    return (AnnotatedExecutableType) getAnnotatedType((Tree) tree);
  }

  /**
   * See {@link #getAnnotatedType(Element)}.
   *
   * @see #getAnnotatedType(Element)
   */
  public final AnnotatedDeclaredType getAnnotatedType(TypeElement elt) {
    return (AnnotatedDeclaredType) getAnnotatedType((Element) elt);
  }

  /**
   * See {@link #getAnnotatedType(Element)}.
   *
   * @see #getAnnotatedType(Element)
   */
  public final AnnotatedExecutableType getAnnotatedType(ExecutableElement elt) {
    return (AnnotatedExecutableType) getAnnotatedType((Element) elt);
  }

  /**
   * See {@link #fromElement(Element)}.
   *
   * @see #fromElement(Element)
   */
  public final AnnotatedDeclaredType fromElement(TypeElement elt) {
    return (AnnotatedDeclaredType) fromElement((Element) elt);
  }

  /**
   * See {@link #fromElement(Element)}.
   *
   * @see #fromElement(Element)
   */
  public final AnnotatedExecutableType fromElement(ExecutableElement elt) {
    return (AnnotatedExecutableType) fromElement((Element) elt);
  }

  // **********************************************************************
  // Helper methods for this classes
  // **********************************************************************

  /**
   * Determines whether the given annotation is a part of the type system under which this type
   * factory operates. Null is never a supported qualifier; the parameter is nullable to allow the
   * result of canonicalAnnotation to be passed in directly.
   *
   * @param a any annotation
   * @return true if that annotation is part of the type system under which this type factory
   *     operates, false otherwise
   */
  public boolean isSupportedQualifier(@Nullable AnnotationMirror a) {
    if (a == null) {
      return false;
    }
    return isSupportedQualifier(AnnotationUtils.annotationName(a));
  }

  /**
   * Determines whether the given class is a part of the type system under which this type factory
   * operates.
   *
   * @param clazz annotation class
   * @return true if that class is a type qualifier in the type system under which this type factory
   *     operates, false otherwise
   */
  public boolean isSupportedQualifier(Class<? extends Annotation> clazz) {
    return getSupportedTypeQualifiers().contains(clazz);
  }

  /**
   * Determines whether the given class name is a part of the type system under which this type
   * factory operates.
   *
   * @param className fully-qualified annotation class name
   * @return true if that class name is a type qualifier in the type system under which this type
   *     factory operates, false otherwise
   */
  public boolean isSupportedQualifier(String className) {
    return getSupportedTypeQualifierNames().contains(className);
  }

  /**
   * Adds the annotation {@code aliasClass} as an alias for the canonical annotation {@code type}
   * that will be used by the Checker Framework in the alias's place.
   *
   * <p>By specifying the alias/canonical relationship using this method, the elements of the alias
   * are not preserved when the canonical annotation to use is constructed from the alias. If you
   * want the elements to be copied over as well, use {@link #addAliasedTypeAnnotation(Class, Class,
   * boolean, String...)}.
   *
   * @param aliasClass the class of the aliased annotation
   * @param type the canonical annotation
   * @deprecated use {@code addAliasedTypeAnnotation}
   */
  @Deprecated // 2020-12-15
  protected void addAliasedAnnotation(Class<?> aliasClass, AnnotationMirror type) {
    addAliasedTypeAnnotation(aliasClass, type);
  }

  /**
   * Adds the annotation {@code aliasClass} as an alias for the canonical annotation {@code
   * canonicalAnno} that will be used by the Checker Framework in the alias's place.
   *
   * <p>By specifying the alias/canonical relationship using this method, the elements of the alias
   * are not preserved when the canonical annotation to use is constructed from the alias. If you
   * want the elements to be copied over as well, use {@link #addAliasedTypeAnnotation(Class, Class,
   * boolean, String...)}.
   *
   * @param aliasClass the class of the aliased annotation
   * @param canonicalAnno the canonical annotation
   */
  protected void addAliasedTypeAnnotation(Class<?> aliasClass, AnnotationMirror canonicalAnno) {
    if (getSupportedTypeQualifiers().contains(aliasClass)) {
      throw new BugInCF(
          "AnnotatedTypeFactory: alias %s should not be in type hierarchy for %s",
          aliasClass, this.getClass().getSimpleName());
    }
    addAliasedTypeAnnotation(aliasClass.getCanonicalName(), canonicalAnno);
  }

  /**
   * Adds the annotation, whose fully-qualified name is given by {@code aliasName}, as an alias for
   * the canonical annotation {@code canonicalAnno} that will be used by the Checker Framework in
   * the alias's place.
   *
   * <p>Use this method if the alias class is not necessarily on the classpath at Checker Framework
   * compile and run time. Otherwise, use {@link #addAliasedTypeAnnotation(Class, AnnotationMirror)}
   * which prevents the possibility of a typo in the class name.
   *
   * @param aliasName the canonical name of the aliased annotation
   * @param canonicalAnno the canonical annotation
   * @deprecated use {@link #addAliasedTypeAnnotation}
   */
  // aliasName is annotated as @FullyQualifiedName because there is no way to confirm that the
  // name of an external annotation is a canoncal name.
  @Deprecated // 2020-12-15
  protected void addAliasedAnnotation(
      @FullyQualifiedName String aliasName, AnnotationMirror canonicalAnno) {
    addAliasedTypeAnnotation(aliasName, canonicalAnno);
  }

  /**
   * Adds the annotation, whose fully-qualified name is given by {@code aliasName}, as an alias for
   * the canonical annotation {@code canonicalAnno} that will be used by the Checker Framework in
   * the alias's place.
   *
   * <p>Use this method if the alias class is not necessarily on the classpath at Checker Framework
   * compile and run time. Otherwise, use {@link #addAliasedTypeAnnotation(Class, AnnotationMirror)}
   * which prevents the possibility of a typo in the class name.
   *
   * @param aliasName the canonical name of the aliased annotation
   * @param canonicalAnno the canonical annotation
   */
  // aliasName is annotated as @FullyQualifiedName because there is no way to confirm that the
  // name of an external annotation is a canoncal name.
  protected void addAliasedTypeAnnotation(
      @FullyQualifiedName String aliasName, AnnotationMirror canonicalAnno) {

    aliases.put(aliasName, new Alias(aliasName, canonicalAnno, false, null, null));
  }

  /**
   * Adds the annotation {@code aliasClass} as an alias for the canonical annotation {@code
   * canonicalAnno} that will be used by the Checker Framework in the alias's place.
   *
   * <p>You may specify the copyElements flag to indicate whether you want the elements of the alias
   * to be copied over when the canonical annotation is constructed as a copy of {@code
   * canonicalAnno}. Be careful that the framework will try to copy the elements by name matching,
   * so make sure that names and types of the elements to be copied over are exactly the same as the
   * ones in the canonical annotation. Otherwise, an 'Couldn't find element in annotation' error is
   * raised.
   *
   * <p>To facilitate the cases where some of the elements are ignored on purpose when constructing
   * the canonical annotation, this method also provides a varargs {@code ignorableElements} for you
   * to explicitly specify the ignoring rules. For example, {@code
   * org.checkerframework.checker.index.qual.IndexFor} is an alias of {@code
   * org.checkerframework.checker.index.qual.NonNegative}, but the element "value" of
   * {@code @IndexFor} should be ignored when constructing {@code @NonNegative}. In the cases where
   * all elements are ignored, we can simply use {@link #addAliasedTypeAnnotation(Class,
   * AnnotationMirror)} instead.
   *
   * @param aliasClass the class of the aliased annotation
   * @param canonical the canonical annotation
   * @param copyElements a flag that indicates whether you want to copy the elements over when
   *     getting the alias from the canonical annotation
   * @param ignorableElements a list of elements that can be safely dropped when the elements are
   *     being copied over
   * @deprecated use {@code addAliasedTypeAnnotation}
   */
  @Deprecated // 2020-12-15
  protected void addAliasedAnnotation(
      Class<?> aliasClass, Class<?> canonical, boolean copyElements, String... ignorableElements) {
    addAliasedTypeAnnotation(aliasClass, canonical, copyElements, ignorableElements);
  }

  /**
   * Adds the annotation {@code aliasClass} as an alias for the canonical annotation {@code
   * canonicalClass} that will be used by the Checker Framework in the alias's place.
   *
   * <p>You may specify the copyElements flag to indicate whether you want the elements of the alias
   * to be copied over when the canonical annotation is constructed as a copy of {@code
   * canonicalClass}. Be careful that the framework will try to copy the elements by name matching,
   * so make sure that names and types of the elements to be copied over are exactly the same as the
   * ones in the canonical annotation. Otherwise, an 'Couldn't find element in annotation' error is
   * raised.
   *
   * <p>To facilitate the cases where some of the elements are ignored on purpose when constructing
   * the canonical annotation, this method also provides a varargs {@code ignorableElements} for you
   * to explicitly specify the ignoring rules. For example, {@code
   * org.checkerframework.checker.index.qual.IndexFor} is an alias of {@code
   * org.checkerframework.checker.index.qual.NonNegative}, but the element "value" of
   * {@code @IndexFor} should be ignored when constructing {@code @NonNegative}. In the cases where
   * all elements are ignored, we can simply use {@link #addAliasedTypeAnnotation(Class,
   * AnnotationMirror)} instead.
   *
   * @param aliasClass the class of the aliased annotation
   * @param canonicalClass the class of the canonical annotation
   * @param copyElements a flag that indicates whether you want to copy the elements over when
   *     getting the alias from the canonical annotation
   * @param ignorableElements a list of elements that can be safely dropped when the elements are
   *     being copied over
   */
  protected void addAliasedTypeAnnotation(
      Class<?> aliasClass,
      Class<?> canonicalClass,
      boolean copyElements,
      String... ignorableElements) {
    if (getSupportedTypeQualifiers().contains(aliasClass)) {
      throw new BugInCF(
          "AnnotatedTypeFactory: alias %s should not be in type hierarchy for %s",
          aliasClass, this.getClass().getSimpleName());
    }
    addAliasedTypeAnnotation(
        aliasClass.getCanonicalName(), canonicalClass, copyElements, ignorableElements);
  }

  /**
   * Adds the annotation, whose fully-qualified name is given by {@code aliasName}, as an alias for
   * the canonical annotation {@code canonicalAnno} that will be used by the Checker Framework in
   * the alias's place.
   *
   * <p>Use this method if the alias class is not necessarily on the classpath at Checker Framework
   * compile and run time. Otherwise, use {@link #addAliasedTypeAnnotation(Class, Class, boolean,
   * String[])} which prevents the possibility of a typo in the class name.
   *
   * @param aliasName the canonical name of the aliased class
   * @param canonicalAnno the canonical annotation
   * @param copyElements a flag that indicates whether we want to copy the elements over when
   *     getting the alias from the canonical annotation
   * @param ignorableElements a list of elements that can be safely dropped when the elements are
   *     being copied over
   */
  // aliasName is annotated as @FullyQualifiedName because there is no way to confirm that the
  // name of an external annotation is a canoncal name.
  protected void addAliasedTypeAnnotation(
      @FullyQualifiedName String aliasName,
      Class<?> canonicalAnno,
      boolean copyElements,
      String... ignorableElements) {
    // The copyElements argument disambiguates overloading.
    if (!copyElements) {
      throw new BugInCF("Do not call with false");
    }
    aliases.put(
        aliasName,
        new Alias(
            aliasName, null, copyElements, canonicalAnno.getCanonicalName(), ignorableElements));
  }

  /**
   * Returns the canonical annotation for the passed annotation. Returns null if the passed
   * annotation is not an alias of a canonical one in the framework.
   *
   * <p>A canonical annotation is the internal annotation that will be used by the Checker Framework
   * in the aliased annotation's place.
   *
   * @param a the qualifier to check for an alias
   * @return the canonical annotation, or null if none exists
   */
  public @Nullable AnnotationMirror canonicalAnnotation(AnnotationMirror a) {
    TypeElement elem = (TypeElement) a.getAnnotationType().asElement();
    String qualName = elem.getQualifiedName().toString();
    Alias alias = aliases.get(qualName);
    if (alias == null) {
      return null;
    }
    if (alias.copyElements) {
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, alias.canonicalName);
      builder.copyElementValuesFromAnnotation(a, alias.ignorableElements);
      return builder.build();
    } else {
      return alias.canonical;
    }
  }

  /**
   * Add the annotation {@code alias} as an alias for the declaration annotation {@code annotation},
   * where the annotation mirror {@code annotationToUse} will be used instead. If multiple calls are
   * made with the same {@code annotation}, then the {@code annotationToUse} must be the same.
   *
   * <p>The point of {@code annotationToUse} is that it may include elements/fields.
   */
  protected void addAliasedDeclAnnotation(
      Class<? extends Annotation> alias,
      Class<? extends Annotation> annotation,
      AnnotationMirror annotationToUse) {
    Pair<AnnotationMirror, Set<Class<? extends Annotation>>> pair = declAliases.get(annotation);
    if (pair != null) {
      if (!AnnotationUtils.areSame(annotationToUse, pair.first)) {
        throw new BugInCF("annotationToUse should be the same: %s %s", pair.first, annotationToUse);
      }
    } else {
      pair = Pair.of(annotationToUse, new HashSet<>());
      declAliases.put(annotation, pair);
    }
    Set<Class<? extends Annotation>> aliases = pair.second;
    aliases.add(alias);
  }

  /**
   * Adds the annotation {@code annotation} in the set of declaration annotations that should be
   * inherited. A declaration annotation will be inherited if it is in this list, or if it has the
   * meta-annotation @InheritedAnnotation. The meta-annotation @InheritedAnnotation should be used
   * instead of this method, if possible.
   */
  protected void addInheritedAnnotation(AnnotationMirror annotation) {
    inheritedAnnotations.add(annotation);
  }

  /**
   * A convenience method that converts a {@link TypeMirror} to an empty {@link AnnotatedTypeMirror}
   * using {@link AnnotatedTypeMirror#createType}.
   *
   * @param t the {@link TypeMirror}
   * @param declaration true if the result should be marked as a type declaration
   * @return an {@link AnnotatedTypeMirror} that has {@code t} as its underlying type
   */
  protected final AnnotatedTypeMirror toAnnotatedType(TypeMirror t, boolean declaration) {
    return AnnotatedTypeMirror.createType(t, this, declaration);
  }

  /**
   * Determines an empty annotated type of the given tree. In other words, finds the {@link
   * TypeMirror} for the tree and converts that into an {@link AnnotatedTypeMirror}, but does not
   * add any annotations to the result.
   *
   * <p>Most users will want to use {@link #getAnnotatedType(Tree)} instead; this method is mostly
   * for internal use.
   *
   * @param node the tree to analyze
   * @return the type of {@code node}, without any annotations
   */
  protected final AnnotatedTypeMirror type(Tree node) {
    boolean isDeclaration = TreeUtils.isTypeDeclaration(node);

    // Attempt to obtain the type via JCTree.
    if (TreeUtils.typeOf(node) != null) {
      AnnotatedTypeMirror result = toAnnotatedType(TreeUtils.typeOf(node), isDeclaration);
      return result;
    }

    // Attempt to obtain the type via TreePath (slower).
    TreePath path = this.getPath(node);
    assert path != null
        : "No path or type in tree: " + node + " [" + node.getClass().getSimpleName() + "]";

    TypeMirror t = trees.getTypeMirror(path);
    assert validType(t) : "Invalid type " + t + " for node " + t;

    AnnotatedTypeMirror result = toAnnotatedType(t, isDeclaration);
    return result;
  }

  /**
   * Gets the declaration tree for the element, if the source is available.
   *
   * <p>TODO: would be nice to move this to InternalUtils/TreeUtils.
   *
   * @param elt an element
   * @return the tree declaration of the element if found
   */
  public final Tree declarationFromElement(Element elt) {
    // if root is null, we cannot find any declaration
    if (root == null) {
      return null;
    }
    if (shouldCache && elementToTreeCache.containsKey(elt)) {
      return elementToTreeCache.get(elt);
    }

    // Check for new declarations, outside of the AST.
    if (elt instanceof DetachedVarSymbol) {
      return ((DetachedVarSymbol) elt).getDeclaration();
    }

    // TODO: handle type parameter declarations?
    Tree fromElt;
    // Prevent calling declarationFor on elements we know we don't have the tree for.

    switch (elt.getKind()) {
      case CLASS:
      case ENUM:
      case INTERFACE:
      case ANNOTATION_TYPE:
      case FIELD:
      case ENUM_CONSTANT:
      case METHOD:
      case CONSTRUCTOR:
        fromElt = trees.getTree(elt);
        break;
      default:
        fromElt =
            com.sun.tools.javac.tree.TreeInfo.declarationFor(
                (com.sun.tools.javac.code.Symbol) elt, (com.sun.tools.javac.tree.JCTree) root);
        break;
    }
    if (shouldCache) {
      elementToTreeCache.put(elt, fromElt);
    }
    return fromElt;
  }

  /**
   * Returns the current class type being visited by the visitor. The method uses the parameter only
   * if the most enclosing class cannot be found directly.
   *
   * @return type of the most enclosing class being visited
   */
  // This method is used to wrap access to visitorState
  protected final ClassTree getCurrentClassTree(Tree tree) {
    if (visitorState.getClassTree() != null) {
      return visitorState.getClassTree();
    }
    return TreePathUtil.enclosingClass(getPath(tree));
  }

  protected final AnnotatedDeclaredType getCurrentClassType(Tree tree) {
    return getAnnotatedType(getCurrentClassTree(tree));
  }

  /**
   * Returns the receiver type of the current method being visited, and returns null if the visited
   * tree is not within a method or if that method has no receiver (e.g. a static method).
   *
   * <p>The method uses the parameter only if the most enclosing method cannot be found directly.
   *
   * @return receiver type of the most enclosing method being visited
   */
  protected final @Nullable AnnotatedDeclaredType getCurrentMethodReceiver(Tree tree) {
    AnnotatedDeclaredType res = visitorState.getMethodReceiver();
    if (res == null) {
      TreePath path = getPath(tree);
      if (path != null) {
        @SuppressWarnings("interning:assignment") // used for == test
        @InternedDistinct MethodTree enclosingMethod = TreePathUtil.enclosingMethod(path);
        ClassTree enclosingClass = TreePathUtil.enclosingClass(path);

        boolean found = false;

        for (Tree member : enclosingClass.getMembers()) {
          if (member.getKind() == Tree.Kind.METHOD) {
            if (member == enclosingMethod) {
              found = true;
            }
          }
        }

        if (found && enclosingMethod != null) {
          AnnotatedExecutableType method = getAnnotatedType(enclosingMethod);
          res = method.getReceiverType();
          // TODO: three tests fail if one adds the following, which would make sense, or not?
          // visitorState.setMethodReceiver(res);
        } else {
          // We are within an anonymous class or field initializer
          res = this.getAnnotatedType(enclosingClass);
        }
      }
    }
    return res;
  }

  protected final boolean isWithinConstructor(Tree tree) {
    if (visitorState.getClassType() != null) {
      return visitorState.getMethodTree() != null
          && TreeUtils.isConstructor(visitorState.getMethodTree());
    }

    MethodTree enclosingMethod = TreePathUtil.enclosingMethod(getPath(tree));
    return enclosingMethod != null && TreeUtils.isConstructor(enclosingMethod);
  }

  /**
   * Gets the path for the given {@link Tree} under the current root by checking from the visitor's
   * current path, and using {@link Trees#getPath(CompilationUnitTree, Tree)} (which is much slower)
   * only if {@code node} is not found on the current path.
   *
   * <p>Note that the given Tree has to be within the current compilation unit, otherwise null will
   * be returned.
   *
   * @param node the {@link Tree} to get the path for
   * @return the path for {@code node} under the current root. Returns null if {@code node} is not
   *     within the current compilation unit.
   */
  public final @Nullable TreePath getPath(@FindDistinct Tree node) {
    assert root != null
        : "AnnotatedTypeFactory.getPath("
            + node.getKind()
            + "): root needs to be set when used on trees; factory: "
            + this.getClass().getSimpleName();

    if (node == null) {
      return null;
    }

    if (artificialTreeToEnclosingElementMap.containsKey(node)) {
      return null;
    }

    if (treePathCache.isCached(node)) {
      return treePathCache.getPath(root, node);
    }

    TreePath currentPath = visitorState.getPath();
    if (currentPath == null) {
      TreePath path = TreePath.getPath(root, node);
      treePathCache.addPath(node, path);
      return path;
    }

    // This method uses multiple heuristics to avoid calling
    // TreePath.getPath()

    // If the current path you are visiting is for this node we are done
    if (currentPath.getLeaf() == node) {
      treePathCache.addPath(node, currentPath);
      return currentPath;
    }

    // When running on Daikon, we noticed that a lot of calls happened
    // within a small subtree containing the node we are currently visiting

    // When testing on Daikon, two steps resulted in the best performance
    if (currentPath.getParentPath() != null) {
      currentPath = currentPath.getParentPath();
      treePathCache.addPath(currentPath.getLeaf(), currentPath);
      if (currentPath.getLeaf() == node) {
        return currentPath;
      }
      if (currentPath.getParentPath() != null) {
        currentPath = currentPath.getParentPath();
        treePathCache.addPath(currentPath.getLeaf(), currentPath);
        if (currentPath.getLeaf() == node) {
          return currentPath;
        }
      }
    }

    final TreePath pathWithinSubtree = TreePath.getPath(currentPath, node);
    if (pathWithinSubtree != null) {
      treePathCache.addPath(node, pathWithinSubtree);
      return pathWithinSubtree;
    }

    // climb the current path till we see that
    // Works when getPath called on the enclosing method, enclosing class.
    TreePath current = currentPath;
    while (current != null) {
      treePathCache.addPath(current.getLeaf(), current);
      if (current.getLeaf() == node) {
        return current;
      }
      current = current.getParentPath();
    }

    // OK, we give up. Use the cache to look up.
    return treePathCache.getPath(root, node);
  }

  /**
   * Gets the {@link Element} representing the declaration of the method enclosing a tree node. This
   * feature is used to record the enclosing methods of {@link Tree}s that are created internally by
   * the checker.
   *
   * <p>TODO: Find a better way to store information about enclosing Trees.
   *
   * @param node the {@link Tree} to get the enclosing method for
   * @return the method {@link Element} enclosing the argument, or null if none has been recorded
   */
  public final Element getEnclosingElementForArtificialTree(Tree node) {
    return artificialTreeToEnclosingElementMap.get(node);
  }

  /**
   * Adds the given mapping from a synthetic (generated) tree to its enclosing element.
   *
   * <p>See {@code
   * org.checkerframework.framework.flow.CFCFGBuilder.CFCFGTranslationPhaseOne.handleArtificialTree(Tree)}.
   *
   * @param tree artifical tree
   * @param enclosing element that encloses {@code tree}
   */
  public final void setEnclosingElementForArtificialTree(Tree tree, Element enclosing) {
    artificialTreeToEnclosingElementMap.put(tree, enclosing);
  }

  /**
   * Assert that the type is a type of valid type mirror, i.e. not an ERROR or OTHER type.
   *
   * @param type an annotated type
   * @return true if the type is a valid annotated type, false otherwise
   */
  static final boolean validAnnotatedType(AnnotatedTypeMirror type) {
    if (type == null) {
      return false;
    }
    return validType(type.getUnderlyingType());
  }

  /**
   * Used for asserting that a type is valid for converting to an annotated type.
   *
   * @return true if {@code type} can be converted to an annotated type, false otherwise
   */
  private static final boolean validType(TypeMirror type) {
    if (type == null) {
      return false;
    }
    switch (type.getKind()) {
      case ERROR:
      case OTHER:
      case PACKAGE:
        return false;
      default:
        return true;
    }
  }

  /**
   * Parses all annotation files in the following order:
   *
   * <ol>
   *   <li>jdk.astub in the same directory as the checker, if it exists and ignorejdkastub option is
   *       not supplied <br>
   *   <li>jdkN.astub, where N is the Java version in the same directory as the checker, if it
   *       exists and ignorejdkastub option is not supplied <br>
   *   <li>Stub files listed in @StubFiles annotation on the checker; must be in same directory as
   *       the checker<br>
   *   <li>Stub files provided via -Astubs compiler option
   *   <li>Ajava files provided via -Aajava compiler option
   * </ol>
   *
   * <p>If a type is annotated with a qualifier from the same hierarchy in more than one stub file,
   * the qualifier in the last stub file is applied.
   *
   * <p>The annotations are stored by side-effecting {@link #stubTypes} and {@link #ajavaTypes}.
   */
  protected void parseAnnotationFiles() {
    stubTypes.parseStubFiles();
    ajavaTypes.parseAjavaFiles();
  }

  /**
   * Returns all of the declaration annotations whose name equals the passed annotation class (or is
   * an alias for it) including annotations:
   *
   * <ul>
   *   <li>on the element
   *   <li>written in stubfiles
   *   <li>inherited from overriden methods, (see {@link InheritedAnnotation})
   *   <li>inherited from superclasses or super interfaces (see {@link Inherited})
   * </ul>
   *
   * @see #getDeclAnnotationNoAliases
   * @param elt the element to retrieve the declaration annotation from
   * @param anno annotation class
   * @return the annotation mirror for anno
   */
  @Override
  public final AnnotationMirror getDeclAnnotation(Element elt, Class<? extends Annotation> anno) {
    return getDeclAnnotation(elt, anno, true);
  }

  /**
   * Returns the actual annotation mirror used to annotate this element, whose name equals the
   * passed annotation class. Returns null if none exists. Does not check for aliases of the
   * annotation class.
   *
   * <p>Call this method from a checker that needs to alias annotations for one purpose and not for
   * another. For example, in the Lock Checker, {@code @LockingFree} and {@code @ReleasesNoLocks}
   * are both aliases of {@code @SideEffectFree} since they are all considered side-effect-free with
   * regard to the set of locks held before and after the method call. However, a {@code
   * synchronized} block is permitted inside a {@code @ReleasesNoLocks} method but not inside a
   * {@code @LockingFree} or {@code @SideEffectFree} method.
   *
   * @see #getDeclAnnotation
   * @param elt the element to retrieve the declaration annotation from
   * @param anno annotation class
   * @return the annotation mirror for anno
   */
  public final AnnotationMirror getDeclAnnotationNoAliases(
      Element elt, Class<? extends Annotation> anno) {
    return getDeclAnnotation(elt, anno, false);
  }

  /**
   * Returns true if the element appears in a stub file (Currently only works for methods,
   * constructors, and fields).
   */
  public boolean isFromStubFile(Element element) {
    return this.getDeclAnnotation(element, FromStubFile.class) != null;
  }

  /**
   * Returns true if the element is from bytecode and the if the element did not appear in a stub
   * file. Currently only works for methods, constructors, and fields.
   */
  public boolean isFromByteCode(Element element) {
    if (isFromStubFile(element)) {
      return false;
    }
    return ElementUtils.isElementFromByteCode(element);
  }

  /**
   * Returns true if redundancy between a stub file and bytecode should be reported.
   *
   * <p>For most type systems the default behavior of returning true is correct. For subcheckers,
   * redundancy in one of the type hierarchies can be ok. Such implementations should return false.
   *
   * @return whether to warn about redundancy between a stub file and bytecode
   */
  public boolean shouldWarnIfStubRedundantWithBytecode() {
    return true;
  }

  /**
   * Returns the actual annotation mirror used to annotate this element, whose name equals the
   * passed annotation class (or is an alias for it). Returns null if none exists. May return the
   * canonical annotation that annotationName is an alias for.
   *
   * <p>This is the private implementation of the same-named, public method.
   *
   * <p>An option is provided to not to check for aliases of annotations. For example, an annotated
   * type factory may use aliasing for a pair of annotations for convenience while needing in some
   * cases to determine a strict ordering between them, such as when determining whether the
   * annotations on an overrider method are more specific than the annotations of an overridden
   * method.
   *
   * @param elt the element to retrieve the annotation from
   * @param annoClass the class the annotation to retrieve
   * @param checkAliases whether to return an annotation mirror for an alias of the requested
   *     annotation class name
   * @return the annotation mirror for the requested annotation, or null if not found
   */
  private AnnotationMirror getDeclAnnotation(
      Element elt, Class<? extends Annotation> annoClass, boolean checkAliases) {
    Set<AnnotationMirror> declAnnos = getDeclAnnotations(elt);

    for (AnnotationMirror am : declAnnos) {
      if (areSameByClass(am, annoClass)) {
        return am;
      }
    }
    // Look through aliases.
    if (checkAliases) {
      Pair<AnnotationMirror, Set<Class<? extends Annotation>>> aliases = declAliases.get(annoClass);
      if (aliases != null) {
        for (Class<? extends Annotation> alias : aliases.second) {
          for (AnnotationMirror am : declAnnos) {
            if (areSameByClass(am, alias)) {
              // TODO: need to copy over elements/fields
              return aliases.first;
            }
          }
        }
      }
    }
    // Not found.
    return null;
  }

  /**
   * Returns all of the declaration annotations on this element including annotations:
   *
   * <ul>
   *   <li>on the element
   *   <li>written in stubfiles
   *   <li>inherited from overriden methods, (see {@link InheritedAnnotation})
   *   <li>inherited from superclasses or super interfaces (see {@link Inherited})
   * </ul>
   *
   * <p>This method returns the actual annotations not their aliases. {@link
   * #getDeclAnnotation(Element, Class)} returns aliases.
   *
   * @param elt the element for which to determine annotations
   * @return all of the declaration annotations on this element, written in stub files, or inherited
   */
  public Set<AnnotationMirror> getDeclAnnotations(Element elt) {
    Set<AnnotationMirror> cachedValue = cacheDeclAnnos.get(elt);
    if (cachedValue != null) {
      // Found in cache, return result.
      return cachedValue;
    }

    Set<AnnotationMirror> results = AnnotationUtils.createAnnotationSet();
    // Retrieving the annotations from the element.
    // This includes annotations inherited from superclasses, but not superinterfaces or
    // overriden methods.
    List<? extends AnnotationMirror> fromEle = elements.getAllAnnotationMirrors(elt);
    for (AnnotationMirror annotation : fromEle) {
      try {
        results.add(annotation);
      } catch (com.sun.tools.javac.code.Symbol.CompletionFailure cf) {
        // If a CompletionFailure occurs, issue a warning.
        checker.reportWarning(
            annotation.getAnnotationType().asElement(),
            "annotation.not.completed",
            ElementUtils.getQualifiedName(elt),
            annotation);
      }
    }

    // If parsing annotation files, return only the annotations in the element.
    if (stubTypes.isParsing()
        || ajavaTypes.isParsing()
        || (currentFileAjavaTypes != null && currentFileAjavaTypes.isParsing())) {
      return results;
    }

    // Add annotations from annotation files.
    results.addAll(stubTypes.getDeclAnnotation(elt));
    results.addAll(ajavaTypes.getDeclAnnotation(elt));
    if (currentFileAjavaTypes != null) {
      results.addAll(currentFileAjavaTypes.getDeclAnnotation(elt));
    }

    if (elt.getKind() == ElementKind.METHOD) {
      // Retrieve the annotations from the overridden method's element.
      inheritOverriddenDeclAnnos((ExecutableElement) elt, results);
    } else if (ElementUtils.isTypeDeclaration(elt)) {
      inheritOverriddenDeclAnnosFromTypeDecl(elt.asType(), results);
    }

    // Add the element and its annotations to the cache.
    cacheDeclAnnos.put(elt, results);
    return results;
  }

  /**
   * Adds into {@code results} the inherited declaration annotations found in all elements of the
   * super types of {@code typeMirror}. (Both superclasses and superinterfaces.)
   *
   * @param typeMirror type
   * @param results set of AnnotationMirrors to which this method adds declarations annotations
   */
  private void inheritOverriddenDeclAnnosFromTypeDecl(
      TypeMirror typeMirror, Set<AnnotationMirror> results) {
    List<? extends TypeMirror> superTypes = types.directSupertypes(typeMirror);
    for (TypeMirror superType : superTypes) {
      TypeElement elt = TypesUtils.getTypeElement(superType);
      if (elt == null) {
        continue;
      }
      Set<AnnotationMirror> superAnnos = getDeclAnnotations(elt);
      for (AnnotationMirror annotation : superAnnos) {
        List<? extends AnnotationMirror> annotationsOnAnnotation;
        try {
          annotationsOnAnnotation =
              annotation.getAnnotationType().asElement().getAnnotationMirrors();
        } catch (com.sun.tools.javac.code.Symbol.CompletionFailure cf) {
          // Fix for Issue 348: If a CompletionFailure occurs, issue a warning.
          checker.reportWarning(
              annotation.getAnnotationType().asElement(),
              "annotation.not.completed",
              ElementUtils.getQualifiedName(elt),
              annotation);
          continue;
        }
        if (containsSameByClass(annotationsOnAnnotation, Inherited.class)
            || AnnotationUtils.containsSameByName(inheritedAnnotations, annotation)) {
          addOrMerge(results, annotation);
        }
      }
    }
  }

  /**
   * Adds into {@code results} the declaration annotations found in all elements that the method
   * element {@code elt} overrides.
   *
   * @param elt method element
   * @param results {@code elt} local declaration annotations. The ones found in stub files and in
   *     the element itself.
   */
  private void inheritOverriddenDeclAnnos(ExecutableElement elt, Set<AnnotationMirror> results) {
    Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods =
        AnnotatedTypes.overriddenMethods(elements, this, elt);

    if (overriddenMethods != null) {
      for (ExecutableElement superElt : overriddenMethods.values()) {
        Set<AnnotationMirror> superAnnos = getDeclAnnotations(superElt);

        for (AnnotationMirror annotation : superAnnos) {
          List<? extends AnnotationMirror> annotationsOnAnnotation;
          try {
            annotationsOnAnnotation =
                annotation.getAnnotationType().asElement().getAnnotationMirrors();
          } catch (com.sun.tools.javac.code.Symbol.CompletionFailure cf) {
            // Fix for Issue 348: If a CompletionFailure occurs,
            // issue a warning.
            checker.reportWarning(
                annotation.getAnnotationType().asElement(),
                "annotation.not.completed",
                ElementUtils.getQualifiedName(elt),
                annotation);
            continue;
          }
          if (containsSameByClass(annotationsOnAnnotation, InheritedAnnotation.class)
              || AnnotationUtils.containsSameByName(inheritedAnnotations, annotation)) {
            addOrMerge(results, annotation);
          }
        }
      }
    }
  }

  private void addOrMerge(Set<AnnotationMirror> results, AnnotationMirror annotation) {
    if (AnnotationUtils.containsSameByName(results, annotation)) {
      /*
       * TODO: feature request: figure out a way to merge multiple annotations
       * of the same kind. For some annotations this might mean merging some
       * arrays, for others it might mean converting a single annotation into a
       * container annotation. We should define a protected method for subclasses
       * to adapt the behavior.
       * For now, do nothing and just take the first, most concrete, annotation.
      AnnotationMirror prev = null;
      for (AnnotationMirror an : results) {
          if (AnnotationUtils.areSameByName(an, annotation)) {
              prev = an;
              break;
          }
      }
      results.remove(prev);
      AnnotationMirror merged = ...;
      results.add(merged);
      */
    } else {
      results.add(annotation);
    }
  }

  /**
   * Returns a list of all declaration annotations used to annotate the element, which have a
   * meta-annotation (i.e., an annotation on that annotation) with class {@code
   * metaAnnotationClass}.
   *
   * @param element the element for which to determine annotations
   * @param metaAnnotationClass the class of the meta-annotation that needs to be present
   * @return a list of pairs {@code (anno, metaAnno)} where {@code anno} is the annotation mirror at
   *     {@code element}, and {@code metaAnno} is the annotation mirror (of type {@code
   *     metaAnnotationClass}) used to meta-annotate the declaration of {@code anno}
   */
  public List<Pair<AnnotationMirror, AnnotationMirror>> getDeclAnnotationWithMetaAnnotation(
      Element element, Class<? extends Annotation> metaAnnotationClass) {
    List<Pair<AnnotationMirror, AnnotationMirror>> result = new ArrayList<>();
    Set<AnnotationMirror> annotationMirrors = getDeclAnnotations(element);

    for (AnnotationMirror candidate : annotationMirrors) {
      List<? extends AnnotationMirror> metaAnnotationsOnAnnotation;
      try {
        metaAnnotationsOnAnnotation =
            candidate.getAnnotationType().asElement().getAnnotationMirrors();
      } catch (com.sun.tools.javac.code.Symbol.CompletionFailure cf) {
        // Fix for Issue 309: If a CompletionFailure occurs, issue a warning.
        // I didn't find a nicer alternative to check whether the Symbol can be completed.
        // The completer field of a Symbol might be non-null also in successful cases.
        // Issue a warning (exception only happens once) and continue.
        checker.reportWarning(
            candidate.getAnnotationType().asElement(),
            "annotation.not.completed",
            ElementUtils.getQualifiedName(element),
            candidate);
        continue;
      }
      // First call copier, if exception, continue normal modula laws.
      for (AnnotationMirror ma : metaAnnotationsOnAnnotation) {
        if (areSameByClass(ma, metaAnnotationClass)) {
          // This candidate has the right kind of meta-annotation.
          // It might be a real contract, or a list of contracts.
          if (isListForRepeatedAnnotation(candidate)) {
            @SuppressWarnings("deprecation") // concrete annotation class is not known
            List<AnnotationMirror> wrappedCandidates =
                AnnotationUtils.getElementValueArray(
                    candidate, "value", AnnotationMirror.class, false);
            for (AnnotationMirror wrappedCandidate : wrappedCandidates) {
              result.add(Pair.of(wrappedCandidate, ma));
            }
          } else {
            result.add(Pair.of(candidate, ma));
          }
        }
      }
    }
    return result;
  }

  /** Cache for {@link #isListForRepeatedAnnotation}. */
  private final Map<DeclaredType, Boolean> isListForRepeatedAnnotationCache = new HashMap<>();

  /**
   * Returns true if the given annotation is a wrapper for multiple repeated annotations.
   *
   * @param a an annotation that might be a wrapper
   * @return true if the argument is a wrapper for multiple repeated annotations
   */
  private boolean isListForRepeatedAnnotation(AnnotationMirror a) {
    DeclaredType annotationType = a.getAnnotationType();
    Boolean resultObject = isListForRepeatedAnnotationCache.get(annotationType);
    if (resultObject != null) {
      return resultObject;
    }
    boolean result = isListForRepeatedAnnotationImplementation(annotationType);
    isListForRepeatedAnnotationCache.put(annotationType, result);
    return result;
  }

  /**
   * Returns true if the annotation is a wrapper for multiple repeated annotations.
   *
   * @param annotationType the declaration of the annotation to test
   * @return true if the annotation is a wrapper for multiple repeated annotations
   */
  private boolean isListForRepeatedAnnotationImplementation(DeclaredType annotationType) {
    TypeMirror enclosingType = annotationType.getEnclosingType();
    if (enclosingType == null) {
      return false;
    }
    if (!annotationType.asElement().getSimpleName().contentEquals("List")) {
      return false;
    }
    List<? extends Element> annoElements = annotationType.asElement().getEnclosedElements();
    if (annoElements.size() != 1) {
      return false;
    }
    // TODO: should check that the type of the single element is: "array of enclosingType".
    return true;
  }

  /**
   * Returns a list of all annotations used to annotate this element, which have a meta-annotation
   * (i.e., an annotation on that annotation) with class {@code metaAnnotationClass}.
   *
   * @param element the element at which to look for annotations
   * @param metaAnnotationClass the class of the meta-annotation that needs to be present
   * @return a list of pairs {@code (anno, metaAnno)} where {@code anno} is the annotation mirror at
   *     {@code element}, and {@code metaAnno} is the annotation mirror used to annotate {@code
   *     anno}.
   */
  public List<Pair<AnnotationMirror, AnnotationMirror>> getAnnotationWithMetaAnnotation(
      Element element, Class<? extends Annotation> metaAnnotationClass) {

    Set<AnnotationMirror> annotationMirrors = AnnotationUtils.createAnnotationSet();
    // Consider real annotations.
    annotationMirrors.addAll(getAnnotatedType(element).getAnnotations());
    // Consider declaration annotations
    annotationMirrors.addAll(getDeclAnnotations(element));

    List<Pair<AnnotationMirror, AnnotationMirror>> result = new ArrayList<>();

    // Go through all annotations found.
    for (AnnotationMirror annotation : annotationMirrors) {
      List<? extends AnnotationMirror> annotationsOnAnnotation =
          annotation.getAnnotationType().asElement().getAnnotationMirrors();
      for (AnnotationMirror a : annotationsOnAnnotation) {
        if (areSameByClass(a, metaAnnotationClass)) {
          result.add(Pair.of(annotation, a));
        }
      }
    }
    return result;
  }

  /**
   * Whether or not the {@code annotatedTypeMirror} has a qualifier parameter.
   *
   * @param annotatedTypeMirror AnnotatedTypeMirror to check
   * @param top the top of the hierarchy to check
   * @return true if the type has a qualifier parameter
   */
  public boolean hasQualifierParameterInHierarchy(
      AnnotatedTypeMirror annotatedTypeMirror, AnnotationMirror top) {
    return AnnotationUtils.containsSame(getQualifierParameterHierarchies(annotatedTypeMirror), top);
  }

  /**
   * Whether or not the {@code element} has a qualifier parameter.
   *
   * @param element element to check
   * @param top the top of the hierarchy to check
   * @return true if the type has a qualifier parameter
   */
  public boolean hasQualifierParameterInHierarchy(@Nullable Element element, AnnotationMirror top) {
    if (element == null) {
      return false;
    }
    return AnnotationUtils.containsSame(getQualifierParameterHierarchies(element), top);
  }

  /**
   * Returns whether the {@code HasQualifierParameter} annotation was explicitly written on {@code
   * element} for the hierarchy given by {@code top}.
   *
   * @param element the Element to check
   * @param top the top qualifier for the hierarchy to check
   * @return whether the class given by {@code element} has been explicitly annotated with {@code
   *     HasQualifierParameter} for the given hierarchy
   */
  public boolean hasExplicitQualifierParameterInHierarchy(Element element, AnnotationMirror top) {
    return AnnotationUtils.containsSame(
        getSupportedAnnotationsInElementAnnotation(
            element, HasQualifierParameter.class, hasQualifierParameterValueElement),
        top);
  }

  /**
   * Returns whether the {@code NoQualifierParameter} annotation was explicitly written on {@code
   * element} for the hierarchy given by {@code top}.
   *
   * @param element the Element to check
   * @param top the top qualifier for the hierarchy to check
   * @return whether the class given by {@code element} has been explicitly annotated with {@code
   *     NoQualifierParameter} for the given hierarchy
   */
  public boolean hasExplicitNoQualifierParameterInHierarchy(Element element, AnnotationMirror top) {
    return AnnotationUtils.containsSame(
        getSupportedAnnotationsInElementAnnotation(
            element, NoQualifierParameter.class, noQualifierParameterValueElement),
        top);
  }

  /**
   * Returns the set of top annotations representing all the hierarchies for which this type has a
   * qualifier parameter.
   *
   * @param annotatedType AnnotatedTypeMirror to check
   * @return the set of top annotations representing all the hierarchies for which this type has a
   *     qualifier parameter
   */
  public Set<AnnotationMirror> getQualifierParameterHierarchies(AnnotatedTypeMirror annotatedType) {
    while (annotatedType.getKind() == TypeKind.TYPEVAR
        || annotatedType.getKind() == TypeKind.WILDCARD) {
      if (annotatedType.getKind() == TypeKind.TYPEVAR) {
        annotatedType = ((AnnotatedTypeVariable) annotatedType).getUpperBound();
      } else if (annotatedType.getKind() == TypeKind.WILDCARD) {
        annotatedType = ((AnnotatedWildcardType) annotatedType).getSuperBound();
      }
    }

    if (annotatedType.getKind() != TypeKind.DECLARED) {
      return Collections.emptySet();
    }

    AnnotatedDeclaredType declaredType = (AnnotatedDeclaredType) annotatedType;
    Element element = declaredType.getUnderlyingType().asElement();
    if (element == null) {
      return Collections.emptySet();
    }
    return getQualifierParameterHierarchies(element);
  }

  /**
   * Returns the set of top annotations representing all the hierarchies for which this element has
   * a qualifier parameter.
   *
   * @param element the Element to check
   * @return the set of top annotations representing all the hierarchies for which this element has
   *     a qualifier parameter
   */
  public Set<AnnotationMirror> getQualifierParameterHierarchies(Element element) {
    if (!ElementUtils.isTypeDeclaration(element)) {
      return Collections.emptySet();
    }

    Set<AnnotationMirror> found = AnnotationUtils.createAnnotationSet();
    found.addAll(
        getSupportedAnnotationsInElementAnnotation(
            element, HasQualifierParameter.class, hasQualifierParameterValueElement));
    Set<AnnotationMirror> hasQualifierParameterTops = AnnotationUtils.createAnnotationSet();
    PackageElement packageElement = ElementUtils.enclosingPackage(element);

    // Traverse all packages containing this element.
    while (packageElement != null) {
      Set<AnnotationMirror> packageDefaultTops =
          getSupportedAnnotationsInElementAnnotation(
              packageElement, HasQualifierParameter.class, hasQualifierParameterValueElement);
      hasQualifierParameterTops.addAll(packageDefaultTops);

      packageElement = ElementUtils.parentPackage(packageElement, elements);
    }

    Set<AnnotationMirror> noQualifierParamClasses =
        getSupportedAnnotationsInElementAnnotation(
            element, NoQualifierParameter.class, noQualifierParameterValueElement);
    for (AnnotationMirror anno : hasQualifierParameterTops) {
      if (!AnnotationUtils.containsSame(noQualifierParamClasses, anno)) {
        found.add(anno);
      }
    }

    return found;
  }

  /**
   * Returns a set of supported annotation mirrors corresponding to the annotation classes listed in
   * the value element of an annotation with class {@code annoClass} on {@code element}.
   *
   * @param element the Element to check
   * @param annoClass the class for an annotation that's written on elements, whose value element is
   *     a list of annotation classes. It is always HasQualifierParameter or NoQualifierParameter
   * @param valueElement the {@code value} field/element of an annotation with class {@code
   *     annoClass}
   * @return the set of supported annotations with classes listed in the value element of an
   *     annotation with class {@code annoClass} on the {@code element}. Returns an empty set if
   *     {@code annoClass} is not written on {@code element} or {@code element} is null.
   */
  private Set<AnnotationMirror> getSupportedAnnotationsInElementAnnotation(
      @Nullable Element element,
      Class<? extends Annotation> annoClass,
      ExecutableElement valueElement) {
    if (element == null) {
      return Collections.emptySet();
    }
    // TODO: caching
    AnnotationMirror annotation = getDeclAnnotation(element, annoClass);
    if (annotation == null) {
      return Collections.emptySet();
    }

    Set<AnnotationMirror> found = AnnotationUtils.createAnnotationSet();
    List<@CanonicalName Name> qualClasses =
        AnnotationUtils.getElementValueClassNames(annotation, valueElement);
    for (Name qual : qualClasses) {
      AnnotationMirror annotationMirror = AnnotationBuilder.fromName(elements, qual);
      if (isSupportedQualifier(annotationMirror)) {
        found.add(annotationMirror);
      }
    }
    return found;
  }

  /**
   * A scanner that replaces annotations in one type with annotations from another. Used by {@link
   * #replaceAnnotations(AnnotatedTypeMirror, AnnotatedTypeMirror)} and {@link
   * #replaceAnnotations(AnnotatedTypeMirror, AnnotatedTypeMirror, AnnotationMirror)}.
   */
  private final AnnotatedTypeReplacer annotatedTypeReplacer = new AnnotatedTypeReplacer();

  /**
   * Replaces or adds all annotations from {@code from} to {@code to}. Annotations from {@code from}
   * will be used everywhere they exist, but annotations in {@code to} will be kept anywhere that
   * {@code from} is unannotated.
   *
   * @param from the annotated type mirror from which to take new annotations
   * @param to the annotated type mirror to which the annotations will be added
   */
  public void replaceAnnotations(final AnnotatedTypeMirror from, final AnnotatedTypeMirror to) {
    annotatedTypeReplacer.visit(from, to);
  }

  /**
   * Replaces or adds annotations in {@code top}'s hierarchy from {@code from} to {@code to}.
   * Annotations from {@code from} will be used everywhere they exist, but annotations in {@code to}
   * will be kept anywhere that {@code from} is unannotated.
   *
   * @param from the annotated type mirror from which to take new annotations
   * @param to the annotated type mirror to which the annotations will be added
   * @param top the top type of the hierarchy whose annotations will be added
   */
  public void replaceAnnotations(
      final AnnotatedTypeMirror from, final AnnotatedTypeMirror to, final AnnotationMirror top) {
    annotatedTypeReplacer.setTop(top);
    annotatedTypeReplacer.visit(from, to);
    annotatedTypeReplacer.setTop(null);
  }

  /** The implementation of the visitor for #containsUninferredTypeArguments. */
  private final SimpleAnnotatedTypeScanner<Boolean, Void> uninferredTypeArgumentScanner =
      new SimpleAnnotatedTypeScanner<>(
          (type, p) ->
              type.getKind() == TypeKind.WILDCARD
                  && ((AnnotatedWildcardType) type).isUninferredTypeArgument(),
          Boolean::logicalOr,
          false);

  /**
   * Returns whether this type or any component type is a wildcard type for which Java 7 type
   * inference is insufficient. See issue 979, or the documentation on AnnotatedWildcardType.
   *
   * @param type type to check
   * @return whether this type or any component type is a wildcard type for which Java 7 type
   *     inference is insufficient
   */
  public boolean containsUninferredTypeArguments(AnnotatedTypeMirror type) {
    return uninferredTypeArgumentScanner.visit(type);
  }

  /**
   * Returns a wildcard type to be used as a type argument when the correct type could not be
   * inferred. The wildcard will be marked as an uninferred wildcard so that {@link
   * AnnotatedWildcardType#isUninferredTypeArgument()} returns true.
   *
   * <p>This method should only be used by type argument inference.
   * org.checkerframework.framework.util.AnnotatedTypes.inferTypeArguments(ProcessingEnvironment,
   * AnnotatedTypeFactory, ExpressionTree, ExecutableElement)
   *
   * @param typeVar TypeVariable which could not be inferred
   * @return a wildcard that is marked as an uninferred type argument
   */
  public AnnotatedWildcardType getUninferredWildcardType(AnnotatedTypeVariable typeVar) {
    final boolean intersectionType;
    final TypeMirror boundType;
    if (typeVar.getUpperBound().getKind() == TypeKind.INTERSECTION) {
      boundType = typeVar.getUpperBound().directSupertypes().get(0).getUnderlyingType();
      intersectionType = true;
    } else {
      boundType = typeVar.getUnderlyingType().getUpperBound();
      intersectionType = false;
    }

    WildcardType wc = types.getWildcardType(boundType, null);
    AnnotatedWildcardType wctype =
        (AnnotatedWildcardType) AnnotatedTypeMirror.createType(wc, this, false);
    wctype.setTypeVariable(typeVar.getUnderlyingType());
    if (!intersectionType) {
      wctype.setExtendsBound(typeVar.getUpperBound().deepCopy());
    } else {
      wctype.getExtendsBound().addAnnotations(typeVar.getUpperBound().getAnnotations());
    }
    wctype.setSuperBound(typeVar.getLowerBound().deepCopy());
    wctype.addAnnotations(typeVar.getAnnotations());
    addDefaultAnnotations(wctype);
    wctype.setUninferredTypeArgument();
    return wctype;
  }

  /**
   * If {@code wildcard}'s upper bound is a super type of {@code annotatedTypeMirror}, this method
   * returns an AnnotatedTypeMirror with the same qualifiers as {@code annotatedTypeMirror}, but the
   * underlying Java type is the most specific base type of {@code annotatedTypeMirror} whose
   * erasure type is equivalent to the upper bound of {@code wildcard}.
   *
   * <p>Otherwise, returns {@code annotatedTypeMirror} unmodified.
   *
   * <p>For example:
   *
   * <pre>
   * wildcard := @NonNull ? extends @NonNull Object
   * annotatedTypeMirror := @Nullable String
   *
   * widenToUpperBound(annotatedTypeMirror, wildcard) returns @Nullable Object
   * </pre>
   *
   * This method is needed because, the Java compiler allows wildcards to have upper bounds above
   * the type variable upper bounds for which they are type arguments. For example, given the
   * following parametric type:
   *
   * <pre>
   * {@code class MyClass<T extends Number>}
   * </pre>
   *
   * the following is legal:
   *
   * <pre>
   * {@code MyClass<? extends Object>}
   * </pre>
   *
   * This is sound because in Java the wildcard is capture converted to: {@code CAP#1 extends Number
   * from capture of ? extends Object}.
   *
   * <p>Because the Checker Framework does not implement capture conversion, wildcard upper bounds
   * may cause spurious errors in subtyping checks. This method prevents those errors by widening
   * the upper bound of the type parameter.
   *
   * <p>This method widens the underlying Java type of the upper bound of the type parameter rather
   * than narrowing the bound of the wildcard in order to avoid issuing an error with an upper bound
   * that is not in source code.
   *
   * <p>The widened type should only be used for typing checks that require it. Using the widened
   * type elsewhere would cause confusing error messages with types not in the source code.
   *
   * @param annotatedTypeMirror AnnotatedTypeMirror to widen
   * @param wildcard AnnotatedWildcardType whose upper bound is used to widen
   * @return {@code annotatedTypeMirror} widen to the upper bound of {@code wildcard}
   */
  public AnnotatedTypeMirror widenToUpperBound(
      final AnnotatedTypeMirror annotatedTypeMirror, final AnnotatedWildcardType wildcard) {
    final TypeMirror toModifyTypeMirror = annotatedTypeMirror.getUnderlyingType();
    final TypeMirror wildcardUBTypeMirror = wildcard.getExtendsBound().getUnderlyingType();
    if (TypesUtils.isErasedSubtype(wildcardUBTypeMirror, toModifyTypeMirror, types)) {
      return annotatedTypeMirror;
    } else if (TypesUtils.isErasedSubtype(toModifyTypeMirror, wildcardUBTypeMirror, types)) {
      return AnnotatedTypes.asSuper(this, annotatedTypeMirror, wildcard);
    } else if (wildcardUBTypeMirror.getKind() == TypeKind.DECLARED
        && TypesUtils.getTypeElement(wildcardUBTypeMirror).getKind().isInterface()) {
      // If the Checker Framework implemented capture conversion, then in this case, then
      // the upper bound of the capture converted wildcard would be an intersection type.
      // See JLS 15.1.10
      // (https://docs.oracle.com/javase/specs/jls/se11/html/jls-5.html#jls-5.1.10)

      // For example:
      // class MyClass<@A T extends @B Number> {}
      // MyClass<@C ? extends @D Serializable>
      // The upper bound of the captured wildcard:
      // glb(@B Number, @D Serializable) = @B Number & @D Serializable
      // The about upper bound must be a subtype of the declared upper bound:
      // @B Number & @D Serializable <: @B Number, which is always true.

      // So, replace the upper bound at the declaration with the wildcard's upper bound so
      // that the rest of the subtyping test pass.
      return wildcard.getExtendsBound();
    }

    return annotatedTypeMirror;
  }

  /**
   * Returns the function type that this member reference targets.
   *
   * <p>The function type is the type of the single method declared in the functional interface
   * adapted as if it were invoked using the functional interface as the receiver expression.
   *
   * <p>The target type of a member reference is the type to which it is assigned or casted.
   *
   * @param tree member reference tree
   * @return the function type that this method reference targets
   */
  public AnnotatedExecutableType getFunctionTypeFromTree(MemberReferenceTree tree) {
    return getFnInterfaceFromTree(tree).second;
  }

  /**
   * Returns the function type that this lambda targets.
   *
   * <p>The function type is the type of the single method declared in the functional interface
   * adapted as if it were invoked using the functional interface as the receiver expression.
   *
   * <p>The target type of a lambda is the type to which it is assigned or casted.
   *
   * @param tree lambda expression tree
   * @return the function type that this lambda targets
   */
  public AnnotatedExecutableType getFunctionTypeFromTree(LambdaExpressionTree tree) {
    return getFnInterfaceFromTree(tree).second;
  }

  /**
   * Returns the functional interface and the function type that this lambda or member references
   * targets.
   *
   * <p>The function type is the type of the single method declared in the functional interface
   * adapted as if it were invoked using the functional interface as the receiver expression.
   *
   * <p>The target type of a lambda or a method reference is the type to which it is assigned or
   * casted.
   *
   * @param tree lambda expression tree or member reference tree
   * @return the functional interface and the function type that this method reference or lambda
   *     targets
   */
  public Pair<AnnotatedTypeMirror, AnnotatedExecutableType> getFnInterfaceFromTree(Tree tree) {

    // Functional interface
    AnnotatedTypeMirror functionalInterfaceType = getFunctionalInterfaceType(tree);
    if (functionalInterfaceType.getKind() == TypeKind.DECLARED) {
      makeGroundTargetType(
          (AnnotatedDeclaredType) functionalInterfaceType, (DeclaredType) TreeUtils.typeOf(tree));
    }

    // Functional method
    Element fnElement = TreeUtils.findFunction(tree, processingEnv);

    // Function type
    AnnotatedExecutableType functionType =
        (AnnotatedExecutableType)
            AnnotatedTypes.asMemberOf(types, this, functionalInterfaceType, fnElement);

    return Pair.of(functionalInterfaceType, functionType);
  }

  /**
   * Get the AnnotatedDeclaredType for the FunctionalInterface from assignment context of the method
   * reference or lambda expression which may be a variable assignment, a method call, or a cast.
   *
   * <p>The assignment context is not always correct, so we must search up the AST. It will
   * recursively search for lambdas nested in lambdas.
   *
   * @param tree the tree of the lambda or method reference
   * @return the functional interface type or an uninferred type argument
   */
  private AnnotatedTypeMirror getFunctionalInterfaceType(Tree tree) {

    Tree parentTree = getPath(tree).getParentPath().getLeaf();
    switch (parentTree.getKind()) {
      case PARENTHESIZED:
        return getFunctionalInterfaceType(parentTree);

      case TYPE_CAST:
        TypeCastTree cast = (TypeCastTree) parentTree;
        assert isFunctionalInterface(
            trees.getTypeMirror(getPath(cast.getType())), parentTree, tree);
        AnnotatedTypeMirror castATM = getAnnotatedType(cast.getType());
        if (castATM.getKind() == TypeKind.INTERSECTION) {
          AnnotatedIntersectionType itype = (AnnotatedIntersectionType) castATM;
          for (AnnotatedTypeMirror t : itype.directSupertypes()) {
            if (TypesUtils.isFunctionalInterface(t.getUnderlyingType(), getProcessingEnv())) {
              return t;
            }
          }
          // We should never reach here: isFunctionalInterface performs the same check
          // and would have raised an error already.
          throw new BugInCF(
              "Expected the type of a cast tree in an assignment context to contain a functional"
                  + " interface bound. Found type: %s for tree: %s in lambda tree: %s",
              castATM, cast, tree);
        }
        return castATM;

      case NEW_CLASS:
        NewClassTree newClass = (NewClassTree) parentTree;
        int indexOfLambda = newClass.getArguments().indexOf(tree);
        ParameterizedExecutableType con = this.constructorFromUse(newClass);
        AnnotatedTypeMirror constructorParam =
            AnnotatedTypes.getAnnotatedTypeMirrorOfParameter(con.executableType, indexOfLambda);
        assert isFunctionalInterface(constructorParam.getUnderlyingType(), parentTree, tree);
        return constructorParam;

      case NEW_ARRAY:
        NewArrayTree newArray = (NewArrayTree) parentTree;
        AnnotatedArrayType newArrayATM = getAnnotatedType(newArray);
        AnnotatedTypeMirror elementATM = newArrayATM.getComponentType();
        assert isFunctionalInterface(elementATM.getUnderlyingType(), parentTree, tree);
        return elementATM;

      case METHOD_INVOCATION:
        MethodInvocationTree method = (MethodInvocationTree) parentTree;
        int index = method.getArguments().indexOf(tree);
        ParameterizedExecutableType exe = this.methodFromUse(method);
        AnnotatedTypeMirror param =
            AnnotatedTypes.getAnnotatedTypeMirrorOfParameter(exe.executableType, index);
        if (param.getKind() == TypeKind.WILDCARD) {
          // param is an uninferred wildcard.
          TypeMirror typeMirror = TreeUtils.typeOf(tree);
          param = AnnotatedTypeMirror.createType(typeMirror, this, false);
          addDefaultAnnotations(param);
        }
        assert isFunctionalInterface(param.getUnderlyingType(), parentTree, tree);
        return param;

      case VARIABLE:
        VariableTree varTree = (VariableTree) parentTree;
        assert isFunctionalInterface(TreeUtils.typeOf(varTree), parentTree, tree);
        return getAnnotatedType(varTree.getType());

      case ASSIGNMENT:
        AssignmentTree assignmentTree = (AssignmentTree) parentTree;
        assert isFunctionalInterface(TreeUtils.typeOf(assignmentTree), parentTree, tree);
        return getAnnotatedType(assignmentTree.getVariable());

      case RETURN:
        Tree enclosing =
            TreePathUtil.enclosingOfKind(
                getPath(parentTree),
                new HashSet<>(Arrays.asList(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION)));

        if (enclosing.getKind() == Tree.Kind.METHOD) {
          MethodTree enclosingMethod = (MethodTree) enclosing;
          return getAnnotatedType(enclosingMethod.getReturnType());
        } else {
          LambdaExpressionTree enclosingLambda = (LambdaExpressionTree) enclosing;
          AnnotatedExecutableType methodExe = getFunctionTypeFromTree(enclosingLambda);
          return methodExe.getReturnType();
        }

      case LAMBDA_EXPRESSION:
        LambdaExpressionTree enclosingLambda = (LambdaExpressionTree) parentTree;
        AnnotatedExecutableType methodExe = getFunctionTypeFromTree(enclosingLambda);
        return methodExe.getReturnType();

      case CONDITIONAL_EXPRESSION:
        ConditionalExpressionTree conditionalExpressionTree =
            (ConditionalExpressionTree) parentTree;
        final AnnotatedTypeMirror falseType =
            getAnnotatedType(conditionalExpressionTree.getFalseExpression());
        final AnnotatedTypeMirror trueType =
            getAnnotatedType(conditionalExpressionTree.getTrueExpression());

        // Known cases where we must use LUB because falseType/trueType will not be equal:
        // a) when one of the types is a type variable that extends a functional interface
        //    or extends a type variable that extends a functional interface
        // b) When one of the two sides of the expression is a reference to a sub-interface.
        //   e.g.   interface ConsumeStr {
        //              public void consume(String s)
        //          }
        //          interface SubConsumer extends ConsumeStr {
        //              default void someOtherMethod() { ... }
        //          }
        //   SubConsumer s = ...;
        //   ConsumeStr stringConsumer = (someCondition) ? s : System.out::println;
        AnnotatedTypeMirror conditionalType =
            AnnotatedTypes.leastUpperBound(this, trueType, falseType);
        assert isFunctionalInterface(conditionalType.getUnderlyingType(), parentTree, tree);
        return conditionalType;

      default:
        throw new BugInCF(
            "Could not find functional interface from assignment context. "
                + "Unexpected tree type: "
                + parentTree.getKind()
                + " For lambda tree: "
                + tree);
    }
  }

  private boolean isFunctionalInterface(TypeMirror typeMirror, Tree contextTree, Tree tree) {
    if (typeMirror.getKind() == TypeKind.WILDCARD) {
      // Ignore wildcards, because they are uninferred type arguments.
      return true;
    }
    Type type = (Type) typeMirror;

    if (!TypesUtils.isFunctionalInterface(type, processingEnv)) {
      if (type.getKind() == TypeKind.INTERSECTION) {
        IntersectionType itype = (IntersectionType) type;
        for (TypeMirror t : itype.getBounds()) {
          if (TypesUtils.isFunctionalInterface(t, processingEnv)) {
            // As long as any of the bounds is a functional interface
            // we should be fine.
            return true;
          }
        }
      }
      throw new BugInCF(
          "Expected the type of %s tree in assignment context to be a functional interface. "
              + "Found type: %s for tree: %s in lambda tree: %s",
          contextTree.getKind(), type, contextTree, tree);
    }
    return true;
  }

  /**
   * Create the ground target type of the functional interface.
   *
   * <p>Basically, it replaces the wildcards with their bounds doing a capture conversion like glb
   * for extends bounds.
   *
   * @see "JLS 9.9"
   * @param functionalType the functional interface type
   * @param groundTargetJavaType the Java type as found by javac
   */
  private void makeGroundTargetType(
      AnnotatedDeclaredType functionalType, DeclaredType groundTargetJavaType) {
    if (functionalType.getTypeArguments().isEmpty()) {
      return;
    }

    List<AnnotatedTypeParameterBounds> bounds =
        this.typeVariablesFromUse(
            functionalType, (TypeElement) functionalType.getUnderlyingType().asElement());

    List<AnnotatedTypeMirror> newTypeArguments = new ArrayList<>(functionalType.getTypeArguments());
    boolean sizesDiffer =
        functionalType.getTypeArguments().size() != groundTargetJavaType.getTypeArguments().size();

    for (int i = 0; i < functionalType.getTypeArguments().size(); i++) {
      AnnotatedTypeMirror argType = functionalType.getTypeArguments().get(i);
      if (argType.getKind() == TypeKind.WILDCARD) {
        AnnotatedWildcardType wildcardType = (AnnotatedWildcardType) argType;

        TypeMirror wildcardUbType = wildcardType.getExtendsBound().getUnderlyingType();

        if (wildcardType.isUninferredTypeArgument()) {
          // Keep the uninferred type so that it is ignored by later subtyping and containment
          // checks.
          newTypeArguments.set(i, wildcardType);
        } else if (isExtendsWildcard(wildcardType)) {
          TypeMirror correctArgType;
          if (sizesDiffer) {
            // The java type is raw.
            TypeMirror typeParamUbType = bounds.get(i).getUpperBound().getUnderlyingType();
            correctArgType =
                TypesUtils.greatestLowerBound(
                    typeParamUbType, wildcardUbType, this.checker.getProcessingEnvironment());
          } else {
            correctArgType = groundTargetJavaType.getTypeArguments().get(i);
          }

          final AnnotatedTypeMirror newArg;
          if (types.isSameType(wildcardUbType, correctArgType)) {
            newArg = wildcardType.getExtendsBound().deepCopy();
          } else if (correctArgType.getKind() == TypeKind.TYPEVAR) {
            newArg = this.toAnnotatedType(correctArgType, false);
            AnnotatedTypeVariable newArgAsTypeVar = (AnnotatedTypeVariable) newArg;
            newArgAsTypeVar
                .getUpperBound()
                .replaceAnnotations(wildcardType.getExtendsBound().getAnnotations());
            newArgAsTypeVar
                .getLowerBound()
                .replaceAnnotations(wildcardType.getSuperBound().getAnnotations());
          } else {
            newArg = this.toAnnotatedType(correctArgType, false);
            newArg.replaceAnnotations(wildcardType.getExtendsBound().getAnnotations());
          }
          newTypeArguments.set(i, newArg);
        } else {
          newTypeArguments.set(i, wildcardType.getSuperBound());
        }
      }
    }
    functionalType.setTypeArguments(newTypeArguments);

    // When the groundTargetJavaType is different from the underlying type of functionalType, only
    // the main annotations are copied.  Add default annotations in places without annotations.
    addDefaultAnnotations(functionalType);
  }

  /**
   * Check that a wildcard is an extends wildcard.
   *
   * @param awt the wildcard type
   * @return true if awt is an extends wildcard
   */
  private boolean isExtendsWildcard(AnnotatedWildcardType awt) {
    return awt.getUnderlyingType().getSuperBound() == null;
  }

  /** Accessor for the element utilities. */
  public Elements getElementUtils() {
    return this.elements;
  }

  /** Accessor for the tree utilities. */
  public Trees getTreeUtils() {
    return this.trees;
  }

  /** Accessor for the processing environment. */
  public ProcessingEnvironment getProcessingEnv() {
    return this.processingEnv;
  }

  /** Matches addition of a constant. */
  static final Pattern plusConstant = Pattern.compile(" *\\+ *(-?[0-9]+)$");
  /** Matches subtraction of a constant. */
  static final Pattern minusConstant = Pattern.compile(" *- *(-?[0-9]+)$");

  /** Matches a string whose only parens are at the beginning and end of the string. */
  private static Pattern surroundingParensPattern = Pattern.compile("^\\([^()]\\)");

  /**
   * Given an expression, split it into a subexpression and a constant offset. For example:
   *
   * <pre>{@code
   * "a" => <"a", "0">
   * "a + 5" => <"a", "5">
   * "a + -5" => <"a", "-5">
   * "a - 5" => <"a", "-5">
   * }</pre>
   *
   * There are methods that can only take as input an expression that represents a JavaExpression.
   * The purpose of this is to pre-process expressions to make those methods more likely to succeed.
   *
   * @param expression an expression to remove a constant offset from
   * @return a sub-expression and a constant offset. The offset is "0" if this routine is unable to
   *     splite the given expression
   */
  // TODO: generalize.  There is no reason this couldn't handle arbitrary addition and subtraction
  // expressions, given the Index Checker's support for OffsetEquation.  That might even make its
  // implementation simpler.
  public static Pair<String, String> getExpressionAndOffset(String expression) {
    String expr = expression;
    String offset = "0";

    // Is this normalization necessary?
    // Remove surrounding whitespace.
    expr = expr.trim();
    // Remove surrounding parentheses.
    if (surroundingParensPattern.matcher(expr).matches()) {
      expr = expr.substring(1, expr.length() - 2).trim();
    }

    Matcher mPlus = plusConstant.matcher(expr);
    Matcher mMinus = minusConstant.matcher(expr);
    if (mPlus.find()) {
      expr = expr.substring(0, mPlus.start());
      offset = mPlus.group(1);
    } else if (mMinus.find()) {
      expr = expr.substring(0, mMinus.start());
      offset = negateConstant(mMinus.group(1));
    }

    if (offset.equals("-0")) {
      offset = "0";
    }

    expr = expr.intern();
    offset = offset.intern();

    return Pair.of(expr, offset);
  }

  /**
   * Given an expression string, returns its negation.
   *
   * @param constantExpression a string representing an integer constant
   * @return the negation of constantExpression
   */
  // Also see Subsequence.negateString which is similar but more sophisticated.
  public static String negateConstant(String constantExpression) {
    if (constantExpression.startsWith("-")) {
      return constantExpression.substring(1);
    } else {
      if (constantExpression.startsWith("+")) {
        constantExpression = constantExpression.substring(1);
      }
      return "-" + constantExpression;
    }
  }

  /**
   * Returns {@code null} or an annotated type mirror that type argument inference should assume
   * {@code expressionTree} is assigned to.
   *
   * <p>If {@code null} is returned, inference proceeds normally.
   *
   * <p>If a type is returned, then inference assumes that {@code expressionTree} was asigned to it.
   * This biases the inference algorithm toward the annotations in the returned type. In particular,
   * if the annotations on type variables in invariant positions are a super type of the annotations
   * inferred, the super type annotations are chosen.
   *
   * <p>This implementation returns null, but subclasses may override this method to return a type.
   *
   * @param expressionTree an expression which has no assignment context and for which type
   *     arguments need to be inferred
   * @return {@code null} or an annotated type mirror that inferrence should pretend {@code
   *     expressionTree} is assigned to
   */
  public @Nullable AnnotatedTypeMirror getDummyAssignedTo(ExpressionTree expressionTree) {
    return null;
  }

  /**
   * Checks that the annotation {@code am} has the name of {@code annoClass}. Values are ignored.
   *
   * <p>This method is faster than {@link AnnotationUtils#areSameByClass(AnnotationMirror, Class)}
   * because it caches the name of the class rather than computing it each time.
   *
   * @param am the AnnotationMirror whose class to compare
   * @param annoClass the class to compare
   * @return true if annoclass is the class of am
   */
  public boolean areSameByClass(AnnotationMirror am, Class<? extends Annotation> annoClass) {
    if (!shouldCache) {
      return AnnotationUtils.areSameByName(am, annoClass.getCanonicalName());
    }
    @SuppressWarnings("nullness") // assume getCanonicalName returns non-null
    String canonicalName = annotationClassNames.computeIfAbsent(annoClass, Class::getCanonicalName);
    return AnnotationUtils.areSameByName(am, canonicalName);
  }

  /**
   * Checks that the collection contains the annotation. Using Collection.contains does not always
   * work, because it does not use areSame for comparison.
   *
   * <p>This method is faster than {@link AnnotationUtils#containsSameByClass(Collection, Class)}
   * because is caches the name of the class rather than computing it each time.
   *
   * @param c a collection of AnnotationMirrors
   * @param anno the annotation class to search for in c
   * @return true iff c contains anno, according to areSameByClass
   */
  public boolean containsSameByClass(
      Collection<? extends AnnotationMirror> c, Class<? extends Annotation> anno) {
    return getAnnotationByClass(c, anno) != null;
  }

  /**
   * Returns the AnnotationMirror in {@code c} that has the same class as {@code anno}.
   *
   * <p>This method is faster than {@link AnnotationUtils#getAnnotationByClass(Collection, Class)}
   * because is caches the name of the class rather than computing it each time.
   *
   * @param c a collection of AnnotationMirrors
   * @param anno the class to search for in c
   * @return AnnotationMirror with the same class as {@code anno} iff c contains anno, according to
   *     areSameByClass; otherwise, {@code null}
   */
  public @Nullable AnnotationMirror getAnnotationByClass(
      Collection<? extends AnnotationMirror> c, Class<? extends Annotation> anno) {
    for (AnnotationMirror an : c) {
      if (areSameByClass(an, anno)) {
        return an;
      }
    }
    return null;
  }

  /**
   * Changes the type of {@code rhsATM} when being assigned to a field, for use by whole-program
   * inference. The default implementation does nothing.
   *
   * @param lhsTree the tree for the field whose type will be changed
   * @param element the element for the field whose type will be changed
   * @param fieldName the name of the field whose type will be changed
   * @param rhsATM the type of the expression being assigned to the field, which is side-effected by
   *     this method
   */
  public void wpiAdjustForUpdateField(
      Tree lhsTree, Element element, String fieldName, AnnotatedTypeMirror rhsATM) {}

  /**
   * Changes the type of {@code rhsATM} when being assigned to anything other than a field, for use
   * by whole-program inference. The default implementation does nothing.
   *
   * @param rhsATM the type of the rhs of the pseudo-assignment, which is side-effected by this
   *     method
   */
  public void wpiAdjustForUpdateNonField(AnnotatedTypeMirror rhsATM) {}

  /**
   * Side-effects the method or constructor annotations to make any desired changes before writing
   * to an annotation file.
   *
   * @param methodAnnos the method or constructor annotations to modify
   */
  public void prepareMethodForWriting(AMethod methodAnnos) {
    // This implementation does nothing.
  }

  /**
   * Side-effects the method or constructor annotations to make any desired changes before writing
   * to an ajava file.
   *
   * @param methodAnnos the method or constructor annotations to modify
   */
  public void prepareMethodForWriting(
      WholeProgramInferenceJavaParserStorage.CallableDeclarationAnnos methodAnnos) {
    // This implementation does nothing.
  }

  /**
   * Does {@code anno}, which is an {@link org.checkerframework.framework.qual.AnnotatedFor}
   * annotation, apply to this checker?
   *
   * @param annotatedForAnno an {@link AnnotatedFor} annotation
   * @return whether {@code anno} applies to this checker
   */
  public boolean doesAnnotatedForApplyToThisChecker(AnnotationMirror annotatedForAnno) {
    List<String> annotatedForCheckers =
        AnnotationUtils.getElementValueArray(
            annotatedForAnno, annotatedForValueElement, String.class);
    for (String annoForChecker : annotatedForCheckers) {
      if (checker.getUpstreamCheckerNames().contains(annoForChecker)
          || CheckerMain.matchesFullyQualifiedProcessor(
              annoForChecker, checker.getUpstreamCheckerNames(), true)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Get the {@code expression} field/element of the given contract annotation.
   *
   * @param contractAnno a {@link RequiresQualifier}, {@link EnsuresQualifier}, or {@link
   *     EnsuresQualifier}
   * @return the {@code expression} field/element of the given annotation
   */
  public List<String> getContractExpressions(AnnotationMirror contractAnno) {
    DeclaredType annoType = contractAnno.getAnnotationType();
    if (types.isSameType(annoType, requiresQualifierTM)) {
      return AnnotationUtils.getElementValueArray(
          contractAnno, requiresQualifierExpressionElement, String.class);
    } else if (types.isSameType(annoType, ensuresQualifierTM)) {
      return AnnotationUtils.getElementValueArray(
          contractAnno, ensuresQualifierExpressionElement, String.class);
    } else if (types.isSameType(annoType, ensuresQualifierIfTM)) {
      return AnnotationUtils.getElementValueArray(
          contractAnno, ensuresQualifierIfExpressionElement, String.class);
    } else {
      throw new BugInCF("Not a contract annotation: " + contractAnno);
    }
  }

  /**
   * Get the {@code value} field/element of the given contract list annotation.
   *
   * @param contractListAnno a {@link RequiresQualifier.List}, {@link EnsuresQualifier.List}, or
   *     {@link EnsuresQualifier.List}
   * @return the {@code value} field/element of the given annotation
   */
  public List<AnnotationMirror> getContractListValues(AnnotationMirror contractListAnno) {
    DeclaredType annoType = contractListAnno.getAnnotationType();
    if (types.isSameType(annoType, requiresQualifierListTM)) {
      return AnnotationUtils.getElementValueArray(
          contractListAnno, requiresQualifierListValueElement, AnnotationMirror.class);
    } else if (types.isSameType(annoType, ensuresQualifierListTM)) {
      return AnnotationUtils.getElementValueArray(
          contractListAnno, ensuresQualifierListValueElement, AnnotationMirror.class);
    } else if (types.isSameType(annoType, ensuresQualifierIfListTM)) {
      return AnnotationUtils.getElementValueArray(
          contractListAnno, ensuresQualifierIfListValueElement, AnnotationMirror.class);
    } else {
      throw new BugInCF("Not a contract list annotation: " + contractListAnno);
    }
  }
}
