package org.checkerframework.framework.type;

import com.google.common.collect.Ordering;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
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.NewClassTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import java.lang.annotation.Annotation;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.StringJoiner;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.checkerframework.checker.formatter.qual.FormatMethod;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.wholeprograminference.WholeProgramInferenceImplementation;
import org.checkerframework.common.wholeprograminference.WholeProgramInferenceJavaParserStorage;
import org.checkerframework.common.wholeprograminference.WholeProgramInferenceScenesStorage;
import org.checkerframework.dataflow.analysis.Analysis;
import org.checkerframework.dataflow.analysis.Analysis.BeforeOrAfter;
import org.checkerframework.dataflow.analysis.AnalysisResult;
import org.checkerframework.dataflow.analysis.TransferInput;
import org.checkerframework.dataflow.analysis.TransferResult;
import org.checkerframework.dataflow.cfg.ControlFlowGraph;
import org.checkerframework.dataflow.cfg.UnderlyingAST;
import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda;
import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod;
import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement;
import org.checkerframework.dataflow.cfg.node.AssignmentNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.ObjectCreationNode;
import org.checkerframework.dataflow.cfg.node.ReturnNode;
import org.checkerframework.dataflow.cfg.visualize.CFGVisualizer;
import org.checkerframework.dataflow.cfg.visualize.DOTCFGVisualizer;
import org.checkerframework.dataflow.expression.FieldAccess;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.dataflow.expression.LocalVariable;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFAbstractStore;
import org.checkerframework.framework.flow.CFAbstractTransfer;
import org.checkerframework.framework.flow.CFAbstractValue;
import org.checkerframework.framework.flow.CFAnalysis;
import org.checkerframework.framework.flow.CFCFGBuilder;
import org.checkerframework.framework.flow.CFStore;
import org.checkerframework.framework.flow.CFTransfer;
import org.checkerframework.framework.flow.CFValue;
import org.checkerframework.framework.qual.DefaultFor;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.checkerframework.framework.qual.DefaultQualifierInHierarchy;
import org.checkerframework.framework.qual.EnsuresQualifier;
import org.checkerframework.framework.qual.EnsuresQualifierIf;
import org.checkerframework.framework.qual.MonotonicQualifier;
import org.checkerframework.framework.qual.QualifierForLiterals;
import org.checkerframework.framework.qual.RelevantJavaTypes;
import org.checkerframework.framework.qual.RequiresQualifier;
import org.checkerframework.framework.qual.TypeUseLocation;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.poly.DefaultQualifierPolymorphism;
import org.checkerframework.framework.type.poly.QualifierPolymorphism;
import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.LiteralTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.PropagationTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.framework.type.typeannotator.DefaultForTypeAnnotator;
import org.checkerframework.framework.type.typeannotator.DefaultQualifierForUseTypeAnnotator;
import org.checkerframework.framework.type.typeannotator.IrrelevantTypeAnnotator;
import org.checkerframework.framework.type.typeannotator.ListTypeAnnotator;
import org.checkerframework.framework.type.typeannotator.PropagationTypeAnnotator;
import org.checkerframework.framework.type.typeannotator.TypeAnnotator;
import org.checkerframework.framework.util.AnnotatedTypes;
import org.checkerframework.framework.util.Contract;
import org.checkerframework.framework.util.ContractsFromMethod;
import org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException;
import org.checkerframework.framework.util.StringToJavaExpression;
import org.checkerframework.framework.util.defaults.QualifierDefaults;
import org.checkerframework.framework.util.dependenttypes.DependentTypesHelper;
import org.checkerframework.framework.util.dependenttypes.DependentTypesTreeAnnotator;
import org.checkerframework.framework.util.typeinference.TypeArgInferenceUtil;
import org.checkerframework.javacutil.AnnotationBuilder;
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.TypeSystemError;
import org.checkerframework.javacutil.TypesUtils;
import org.checkerframework.javacutil.UserError;
import org.plumelib.reflection.Signatures;
import org.plumelib.util.CollectionsPlume;
import org.plumelib.util.SystemPlume;
import scenelib.annotations.el.AField;
import scenelib.annotations.el.AMethod;

/**
 * A factory that extends {@link AnnotatedTypeFactory} to optionally use flow-sensitive qualifier
 * inference.
 *
 * <p>It also adds other features: qualifier polymorphism, default annotations via {@link
 * DefaultFor}, user-specified defaults via {@link DefaultQualifier}, standardization via {@link
 * DependentTypesHelper}, etc. Those features, and {@link #addComputedTypeAnnotations} (other than
 * the part related to flow-sensitivity), could and should be in the superclass {@link
 * AnnotatedTypeFactory}; it is not clear why they are defined in this class.
 */
public abstract class GenericAnnotatedTypeFactory<
        Value extends CFAbstractValue<Value>,
        Store extends CFAbstractStore<Value, Store>,
        TransferFunction extends CFAbstractTransfer<Value, Store, TransferFunction>,
        FlowAnalysis extends CFAbstractAnalysis<Value, Store, TransferFunction>>
    extends AnnotatedTypeFactory {

  /** Should use flow by default. */
  protected static boolean flowByDefault = true;

  /** To cache the supported monotonic type qualifiers. */
  private Set<Class<? extends Annotation>> supportedMonotonicQuals;

  /** to annotate types based on the given tree */
  protected TypeAnnotator typeAnnotator;

  /** for use in addAnnotationsFromDefaultForType */
  private DefaultQualifierForUseTypeAnnotator defaultQualifierForUseTypeAnnotator;

  /** for use in addAnnotationsFromDefaultForType */
  private DefaultForTypeAnnotator defaultForTypeAnnotator;

  /** to annotate types based on the given un-annotated types */
  protected TreeAnnotator treeAnnotator;

  /** to handle any polymorphic types */
  protected QualifierPolymorphism poly;

  /** to handle defaults specified by the user */
  protected QualifierDefaults defaults;

  /** To handle dependent type annotations and contract expressions. */
  protected DependentTypesHelper dependentTypesHelper;

  /** to handle method pre- and postconditions */
  protected ContractsFromMethod contractsUtils;

  /**
   * The Java types on which users may write this type system's type annotations. null means no
   * restrictions. Arrays are handled by separate field {@code #arraysAreRelevant}.
   *
   * <p>If the relevant type is generic, this contains its erasure.
   *
   * <p>Although a {@code Class<?>} object exists for every element, this does not contain those
   * {@code Class<?>} objects because the elements will be compared to TypeMirrors for which Class
   * objects may not exist (they might not be on the classpath).
   */
  public @Nullable Set<TypeMirror> relevantJavaTypes;

  /**
   * Whether users may write type annotations on arrays. Ignored unless {@link #relevantJavaTypes}
   * is non-null.
   */
  boolean arraysAreRelevant = false;

  // Flow related fields

  /**
   * Should use flow-sensitive type refinement analysis? This value can be changed when an
   * AnnotatedTypeMirror without annotations from data flow is required.
   *
   * @see #getAnnotatedTypeLhs(Tree)
   */
  private boolean useFlow;

  /** Is this type factory configured to use flow-sensitive type refinement? */
  private final boolean everUseFlow;

  /**
   * Should the local variable default annotation be applied to type variables?
   *
   * <p>It is initialized to true if data flow is used by the checker. It is set to false when
   * getting the assignment context for type argument inference.
   *
   * @see GenericAnnotatedTypeFactory#getAnnotatedTypeLhsNoTypeVarDefault
   */
  private boolean shouldDefaultTypeVarLocals;

  /**
   * Elements representing variables for which the type of the initializer is being determined in
   * order to apply qualifier parameter defaults.
   *
   * <p>Local variables with a qualifier parameter get their declared type from the type of their
   * initializer. Sometimes the initializer's type depends on the type of the variable, such as
   * during type variable inference or when a variable is used in its own initializer as in "Object
   * o = (o = null)". This creates a circular dependency resulting in infinite recursion. To prevent
   * this, variables in this set should not be typed based on their initializer, but by using normal
   * defaults.
   *
   * <p>This set should only be modified in
   * GenericAnnotatedTypeFactory#applyLocalVariableQualifierParameterDefaults which clears variables
   * after computing their initializer types.
   *
   * @see GenericAnnotatedTypeFactory#applyLocalVariableQualifierParameterDefaults
   */
  private Set<VariableElement> variablesUnderInitialization;

  /**
   * Caches types of initializers for local variables with a qualifier parameter, so that they
   * aren't computed each time the type of a variable is looked up.
   *
   * @see GenericAnnotatedTypeFactory#applyLocalVariableQualifierParameterDefaults
   */
  private Map<Tree, AnnotatedTypeMirror> initializerCache;

  /**
   * Should the analysis assume that side effects to a value can change the type of aliased
   * references?
   *
   * <p>For many type systems, once a local variable's type is refined, side effects to the
   * variable's value do not change the variable's type annotations. For some type systems, a side
   * effect to the value could change them; set this field to true.
   */
  // Not final so that subclasses can set it.
  public boolean sideEffectsUnrefineAliases = false;

  /**
   * True if this checker either has one or more subcheckers, or if this checker is a subchecker.
   * False otherwise. All uses of the methods {@link #addSharedCFGForTree(Tree, ControlFlowGraph)}
   * and {@link #getSharedCFGForTree(Tree)} should be guarded by a check that this is true.
   */
  public final boolean hasOrIsSubchecker;

  /** An empty store. */
  // Set in postInit only
  protected Store emptyStore;

  // Set in postInit only
  protected FlowAnalysis analysis;

  // Set in postInit only
  protected TransferFunction transfer;

  // Maintain for every class the store that is used when we analyze initialization code
  protected Store initializationStore;

  // Maintain for every class the store that is used when we analyze static initialization code
  protected Store initializationStaticStore;

  /**
   * Caches for {@link AnalysisResult#runAnalysisFor(Node, Analysis.BeforeOrAfter, TransferInput,
   * IdentityHashMap, Map)}. This cache is enabled if {@link #shouldCache} is true. The cache size
   * is derived from {@link #getCacheSize()}.
   *
   * @see AnalysisResult#runAnalysisFor(Node, Analysis.BeforeOrAfter, TransferInput,
   *     IdentityHashMap, Map)
   */
  protected final Map<
          TransferInput<Value, Store>, IdentityHashMap<Node, TransferResult<Value, Store>>>
      flowResultAnalysisCaches;

  /**
   * Subcheckers share the same ControlFlowGraph for each analyzed code statement. This maps from
   * code statements to the shared control flow graphs. This map is null in all subcheckers (i.e.
   * any checker for which getParentChecker() returns non-null). This map is also unused (and
   * therefore null) for a checker with no subcheckers with which it can share CFGs.
   *
   * <p>The initial capacity of the map is set by {@link #getCacheSize()}.
   */
  protected @Nullable Map<Tree, ControlFlowGraph> subcheckerSharedCFG;

  /**
   * If true, {@link #setRoot(CompilationUnitTree)} should clear the {@link #subcheckerSharedCFG}
   * map, freeing memory.
   *
   * <p>For each compilation unit, all the subcheckers run first and finally the ultimate parent
   * checker runs. The ultimate parent checker's {@link #setRoot(CompilationUnitTree)} (the last to
   * run) sets this field to true.
   *
   * <p>In first subchecker to run for the next compilation unit, {@link
   * #setRoot(CompilationUnitTree)} observes the true value, clears the {@link #subcheckerSharedCFG}
   * map, and sets this field back to false. That first subchecker will create a CFG and re-populate
   * the map, and subsequent subcheckers will use the map.
   */
  protected boolean shouldClearSubcheckerSharedCFGs = true;

  /**
   * Creates a type factory. Its compilation unit is not yet set.
   *
   * @param checker the checker to which this type factory belongs
   * @param useFlow whether flow analysis should be performed
   */
  protected GenericAnnotatedTypeFactory(BaseTypeChecker checker, boolean useFlow) {
    super(checker);

    this.everUseFlow = useFlow;
    this.shouldDefaultTypeVarLocals = useFlow;
    this.useFlow = useFlow;

    this.variablesUnderInitialization = new HashSet<>();
    this.scannedClasses = new HashMap<>();
    this.flowResult = null;
    this.regularExitStores = null;
    this.exceptionalExitStores = null;
    this.methodInvocationStores = null;
    this.returnStatementStores = null;

    this.initializationStore = null;
    this.initializationStaticStore = null;

    this.cfgVisualizer = createCFGVisualizer();

    if (shouldCache) {
      int cacheSize = getCacheSize();
      flowResultAnalysisCaches = CollectionUtils.createLRUCache(cacheSize);
      initializerCache = CollectionUtils.createLRUCache(cacheSize);
    } else {
      flowResultAnalysisCaches = null;
      initializerCache = null;
    }

    RelevantJavaTypes relevantJavaTypesAnno =
        checker.getClass().getAnnotation(RelevantJavaTypes.class);
    if (relevantJavaTypesAnno == null) {
      this.relevantJavaTypes = null;
      this.arraysAreRelevant = true;
    } else {
      Types types = getChecker().getTypeUtils();
      Elements elements = getElementUtils();
      Class<?>[] classes = relevantJavaTypesAnno.value();
      this.relevantJavaTypes = new HashSet<>(CollectionsPlume.mapCapacity(classes.length));
      this.arraysAreRelevant = false;
      for (Class<?> clazz : classes) {
        if (clazz == Object[].class) {
          arraysAreRelevant = true;
        } else if (clazz.isArray()) {
          throw new TypeSystemError(
              "Don't use arrays other than Object[] in @RelevantJavaTypes on "
                  + this.getClass().getSimpleName());
        } else {
          TypeMirror relevantType = TypesUtils.typeFromClass(clazz, types, elements);
          relevantJavaTypes.add(types.erasure(relevantType));
        }
      }
    }

    contractsUtils = createContractsFromMethod();

    hasOrIsSubchecker =
        !this.getChecker().getSubcheckers().isEmpty()
            || this.getChecker().getParentChecker() != null;

    // Every subclass must call postInit, but it must be called after
    // all other initialization is finished.
  }

  @Override
  protected void postInit() {
    super.postInit();

    this.dependentTypesHelper = createDependentTypesHelper();
    this.defaults = createAndInitQualifierDefaults();
    this.treeAnnotator = createTreeAnnotator();
    this.typeAnnotator = createTypeAnnotator();
    this.defaultQualifierForUseTypeAnnotator = createDefaultForUseTypeAnnotator();
    this.defaultForTypeAnnotator = createDefaultForTypeAnnotator();

    this.poly = createQualifierPolymorphism();

    this.analysis = createFlowAnalysis(new ArrayList<>());
    this.transfer = analysis.getTransferFunction();
    this.emptyStore = analysis.createEmptyStore(transfer.usesSequentialSemantics());

    this.parseAnnotationFiles();
  }

  /**
   * Performs flow-sensitive type refinement on {@code classTree} if this type factory is configured
   * to do so.
   *
   * @param classTree tree on which to perform flow-sensitive type refinement
   */
  @Override
  public void preProcessClassTree(ClassTree classTree) {
    if (this.everUseFlow) {
      checkAndPerformFlowAnalysis(classTree);
    }
  }

  /**
   * Creates a type factory. Its compilation unit is not yet set.
   *
   * @param checker the checker to which this type factory belongs
   */
  protected GenericAnnotatedTypeFactory(BaseTypeChecker checker) {
    this(checker, flowByDefault);
  }

  @Override
  public void setRoot(@Nullable CompilationUnitTree root) {
    super.setRoot(root);
    this.scannedClasses.clear();
    this.flowResult = null;
    this.regularExitStores = null;
    this.exceptionalExitStores = null;
    this.methodInvocationStores = null;
    this.returnStatementStores = null;
    this.initializationStore = null;
    this.initializationStaticStore = null;

    if (shouldCache) {
      this.flowResultAnalysisCaches.clear();
      this.initializerCache.clear();
      this.defaultQualifierForUseTypeAnnotator.clearCache();

      if (this.checker.getParentChecker() == null) {
        // This is an ultimate parent checker, so after it runs the shared CFG it is using
        // will no longer be needed, and can be cleared.
        this.shouldClearSubcheckerSharedCFGs = true;
        if (this.checker.getSubcheckers().isEmpty()) {
          // If this checker has no subcheckers, then any maps that are currently
          // being maintained should be cleared right away.
          clearSharedCFG(this);
        }
      } else {
        GenericAnnotatedTypeFactory<?, ?, ?, ?> ultimateParentATF =
            this.checker.getUltimateParentChecker().getTypeFactory();
        clearSharedCFG(ultimateParentATF);
      }
    }
  }

  /**
   * Clears the caches associated with the shared CFG for the given type factory, if it is safe to
   * do so.
   *
   * @param factory a type factory
   */
  private void clearSharedCFG(GenericAnnotatedTypeFactory<?, ?, ?, ?> factory) {
    if (factory.shouldClearSubcheckerSharedCFGs) {
      // This is the first subchecker running in a group that share CFGs, so it must clear its
      // ultimate parent's shared CFG before adding a new shared CFG.
      factory.shouldClearSubcheckerSharedCFGs = false;
      if (factory.subcheckerSharedCFG != null) {
        factory.subcheckerSharedCFG.clear();
      }
      // The same applies to this map.
      factory.artificialTreeToEnclosingElementMap.clear();
    }
  }

  // **********************************************************************
  // Factory Methods for the appropriate annotator classes
  // **********************************************************************

  /**
   * Returns an immutable set of the <em>monotonic</em> type qualifiers supported by this checker.
   *
   * @return the monotonic type qualifiers supported this processor, or an empty set if none
   * @see MonotonicQualifier
   */
  public final Set<Class<? extends Annotation>> getSupportedMonotonicTypeQualifiers() {
    if (supportedMonotonicQuals == null) {
      supportedMonotonicQuals = new HashSet<>();
      for (Class<? extends Annotation> anno : getSupportedTypeQualifiers()) {
        MonotonicQualifier mono = anno.getAnnotation(MonotonicQualifier.class);
        if (mono != null) {
          supportedMonotonicQuals.add(anno);
        }
      }
    }
    return supportedMonotonicQuals;
  }

  /**
   * Returns a {@link TreeAnnotator} that adds annotations to a type based on the contents of a
   * tree.
   *
   * <p>The default tree annotator is a {@link ListTreeAnnotator} of the following:
   *
   * <ol>
   *   <li>{@link PropagationTreeAnnotator}: Propagates annotations from subtrees
   *   <li>{@link LiteralTreeAnnotator}: Adds annotations based on {@link QualifierForLiterals}
   *       meta-annotations
   *   <li>{@link DependentTypesTreeAnnotator}: Adapts dependent annotations based on context
   * </ol>
   *
   * <p>Subclasses may override this method to specify additional tree annotators, for example:
   *
   * <pre>
   * new ListTreeAnnotator(super.createTreeAnnotator(), new KeyLookupTreeAnnotator(this));
   * </pre>
   *
   * @return a tree annotator
   */
  protected TreeAnnotator createTreeAnnotator() {
    List<TreeAnnotator> treeAnnotators = new ArrayList<>(2);
    treeAnnotators.add(new PropagationTreeAnnotator(this));
    treeAnnotators.add(new LiteralTreeAnnotator(this).addStandardLiteralQualifiers());
    if (dependentTypesHelper.hasDependentAnnotations()) {
      treeAnnotators.add(dependentTypesHelper.createDependentTypesTreeAnnotator());
    }
    return new ListTreeAnnotator(treeAnnotators);
  }

  /**
   * Returns a {@link DefaultForTypeAnnotator} that adds annotations to a type based on the content
   * of the type itself.
   *
   * <p>Subclass may override this method. The default type annotator is a {@link ListTypeAnnotator}
   * of the following:
   *
   * <ol>
   *   <li>{@link IrrelevantTypeAnnotator}: Adds top to types not listed in the {@code @}{@link
   *       RelevantJavaTypes} annotation on the checker.
   *   <li>{@link PropagationTypeAnnotator}: Propagates annotation onto wildcards.
   * </ol>
   *
   * @return a type annotator
   */
  protected TypeAnnotator createTypeAnnotator() {
    List<TypeAnnotator> typeAnnotators = new ArrayList<>(1);
    if (relevantJavaTypes != null) {
      typeAnnotators.add(
          new IrrelevantTypeAnnotator(this, getQualifierHierarchy().getTopAnnotations()));
    }
    typeAnnotators.add(new PropagationTypeAnnotator(this));
    return new ListTypeAnnotator(typeAnnotators);
  }

  /**
   * Creates an {@link DefaultQualifierForUseTypeAnnotator}.
   *
   * @return a new {@link DefaultQualifierForUseTypeAnnotator}
   */
  protected DefaultQualifierForUseTypeAnnotator createDefaultForUseTypeAnnotator() {
    return new DefaultQualifierForUseTypeAnnotator(this);
  }

  /**
   * Creates an {@link DefaultForTypeAnnotator}.
   *
   * @return a new {@link DefaultForTypeAnnotator}
   */
  protected DefaultForTypeAnnotator createDefaultForTypeAnnotator() {
    return new DefaultForTypeAnnotator(this);
  }

  /**
   * Returns the {@link DefaultForTypeAnnotator}.
   *
   * @return the {@link DefaultForTypeAnnotator}
   */
  public DefaultForTypeAnnotator getDefaultForTypeAnnotator() {
    return defaultForTypeAnnotator;
  }

  /**
   * Returns the appropriate flow analysis class that is used for the org.checkerframework.dataflow
   * analysis.
   *
   * <p>This implementation uses the checker naming convention to create the appropriate analysis.
   * If no transfer function is found, it returns an instance of {@link CFAnalysis}.
   *
   * <p>Subclasses have to override this method to create the appropriate analysis if they do not
   * follow the checker naming convention.
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  protected FlowAnalysis createFlowAnalysis(List<Pair<VariableElement, Value>> fieldValues) {

    // Try to reflectively load the visitor.
    Class<?> checkerClass = checker.getClass();

    while (checkerClass != BaseTypeChecker.class) {
      FlowAnalysis result =
          BaseTypeChecker.invokeConstructorFor(
              BaseTypeChecker.getRelatedClassName(checkerClass, "Analysis"),
              new Class<?>[] {BaseTypeChecker.class, this.getClass(), List.class},
              new Object[] {checker, this, fieldValues});
      if (result != null) {
        return result;
      }
      checkerClass = checkerClass.getSuperclass();
    }

    // If an analysis couldn't be loaded reflectively, return the default.
    List<Pair<VariableElement, CFValue>> tmp =
        CollectionsPlume.mapList(
            (Pair<VariableElement, Value> fieldVal) ->
                Pair.of(fieldVal.first, (CFValue) fieldVal.second),
            fieldValues);
    return (FlowAnalysis) new CFAnalysis(checker, (GenericAnnotatedTypeFactory) this, tmp);
  }

  /**
   * Returns the appropriate transfer function that is used for the org.checkerframework.dataflow
   * analysis.
   *
   * <p>This implementation uses the checker naming convention to create the appropriate transfer
   * function. If no transfer function is found, it returns an instance of {@link CFTransfer}.
   *
   * <p>Subclasses have to override this method to create the appropriate transfer function if they
   * do not follow the checker naming convention.
   */
  // A more precise type for the parameter would be FlowAnalysis, which
  // is the type parameter bounded by the current parameter type CFAbstractAnalysis<Value, Store,
  // TransferFunction>.
  // However, we ran into issues in callers of the method if we used that type.
  public TransferFunction createFlowTransferFunction(
      CFAbstractAnalysis<Value, Store, TransferFunction> analysis) {

    // Try to reflectively load the visitor.
    Class<?> checkerClass = checker.getClass();

    while (checkerClass != BaseTypeChecker.class) {
      TransferFunction result =
          BaseTypeChecker.invokeConstructorFor(
              BaseTypeChecker.getRelatedClassName(checkerClass, "Transfer"),
              new Class<?>[] {analysis.getClass()},
              new Object[] {analysis});
      if (result != null) {
        return result;
      }
      checkerClass = checkerClass.getSuperclass();
    }

    // If a transfer function couldn't be loaded reflectively, return the default.
    @SuppressWarnings("unchecked")
    TransferFunction ret =
        (TransferFunction)
            new CFTransfer((CFAbstractAnalysis<CFValue, CFStore, CFTransfer>) analysis);
    return ret;
  }

  /**
   * Creates a {@link DependentTypesHelper} and returns it. Use {@link #getDependentTypesHelper} to
   * access the value.
   *
   * @return a new {@link DependentTypesHelper}
   */
  protected DependentTypesHelper createDependentTypesHelper() {
    return new DependentTypesHelper(this);
  }

  /**
   * Returns the DependentTypesHelper.
   *
   * @return the DependentTypesHelper
   */
  public DependentTypesHelper getDependentTypesHelper() {
    return dependentTypesHelper;
  }

  /**
   * Creates an {@link ContractsFromMethod} and returns it.
   *
   * @return a new {@link ContractsFromMethod}
   */
  protected ContractsFromMethod createContractsFromMethod() {
    return new ContractsFromMethod(this);
  }

  /**
   * Returns the helper for method pre- and postconditions.
   *
   * @return the helper for method pre- and postconditions
   */
  public ContractsFromMethod getContractsFromMethod() {
    return contractsUtils;
  }

  @Override
  public AnnotatedDeclaredType fromNewClass(NewClassTree newClassTree) {
    AnnotatedDeclaredType superResult = super.fromNewClass(newClassTree);
    dependentTypesHelper.atExpression(superResult, newClassTree);
    return superResult;
  }

  /**
   * Create {@link QualifierDefaults} which handles checker specified defaults, and initialize the
   * created {@link QualifierDefaults}. Subclasses should override {@link
   * GenericAnnotatedTypeFactory#addCheckedCodeDefaults(QualifierDefaults defs)} to add more
   * defaults or use different defaults.
   *
   * @return the QualifierDefaults object
   */
  // TODO: When changing this method, also look into
  // {@link
  // org.checkerframework.common.wholeprograminference.WholeProgramInferenceScenesHelper#shouldIgnore}.
  // Both methods should have some functionality merged into a single location.
  // See Issue 683
  // https://github.com/typetools/checker-framework/issues/683
  protected final QualifierDefaults createAndInitQualifierDefaults() {
    QualifierDefaults defs = createQualifierDefaults();
    addCheckedCodeDefaults(defs);
    addCheckedStandardDefaults(defs);
    addUncheckedStandardDefaults(defs);
    checkForDefaultQualifierInHierarchy(defs);

    return defs;
  }

  /**
   * Create {@link QualifierDefaults} which handles checker specified defaults. Sub-classes override
   * this method to provide a different {@code QualifierDefault} implementation.
   */
  protected QualifierDefaults createQualifierDefaults() {
    return new QualifierDefaults(elements, this);
  }

  /**
   * Creates and returns a string containing the number of qualifiers and the canonical class names
   * of each qualifier that has been added to this checker's supported qualifier set. The names are
   * alphabetically sorted.
   *
   * @return a string containing the number of qualifiers and canonical names of each qualifier
   */
  protected final String getSortedQualifierNames() {
    Set<Class<? extends Annotation>> stq = getSupportedTypeQualifiers();
    if (stq.isEmpty()) {
      return "No qualifiers examined";
    }
    if (stq.size() == 1) {
      return "1 qualifier examined: " + stq.iterator().next().getCanonicalName();
    }

    // Create a list of the supported qualifiers and sort the list alphabetically
    List<Class<? extends Annotation>> sortedSupportedQuals = new ArrayList<>(stq);
    sortedSupportedQuals.sort(Comparator.comparing(Class::getCanonicalName));

    // display the number of qualifiers as well as the names of each qualifier.
    StringJoiner sj =
        new StringJoiner(", ", sortedSupportedQuals.size() + " qualifiers examined: ", "");
    for (Class<? extends Annotation> qual : sortedSupportedQuals) {
      sj.add(qual.getCanonicalName());
    }
    return sj.toString();
  }

  /**
   * Adds default qualifiers for type-checked code by reading {@link DefaultFor} and {@link
   * DefaultQualifierInHierarchy} meta-annotations. Subclasses may override this method to add
   * defaults that cannot be specified with a {@link DefaultFor} or {@link
   * DefaultQualifierInHierarchy} meta-annotations.
   *
   * @param defs QualifierDefault object to which defaults are added
   */
  protected void addCheckedCodeDefaults(QualifierDefaults defs) {
    // Add defaults from @DefaultFor and @DefaultQualifierInHierarchy
    for (Class<? extends Annotation> qual : getSupportedTypeQualifiers()) {
      DefaultFor defaultFor = qual.getAnnotation(DefaultFor.class);
      if (defaultFor != null) {
        final TypeUseLocation[] locations = defaultFor.value();
        defs.addCheckedCodeDefaults(AnnotationBuilder.fromClass(elements, qual), locations);
      }

      if (qual.getAnnotation(DefaultQualifierInHierarchy.class) != null) {
        defs.addCheckedCodeDefault(
            AnnotationBuilder.fromClass(elements, qual), TypeUseLocation.OTHERWISE);
      }
    }
  }

  /**
   * Adds the standard CLIMB defaults that do not conflict with previously added defaults.
   *
   * @param defs {@link QualifierDefaults} object to which defaults are added
   */
  protected void addCheckedStandardDefaults(QualifierDefaults defs) {
    if (this.everUseFlow) {
      defs.addClimbStandardDefaults();
    }
  }

  /**
   * Adds standard unchecked defaults that do not conflict with previously added defaults.
   *
   * @param defs {@link QualifierDefaults} object to which defaults are added
   */
  protected void addUncheckedStandardDefaults(QualifierDefaults defs) {
    defs.addUncheckedStandardDefaults();
  }

  /**
   * Check that a default qualifier (in at least one hierarchy) has been set and issue an error if
   * not.
   *
   * @param defs {@link QualifierDefaults} object to which defaults are added
   */
  protected void checkForDefaultQualifierInHierarchy(QualifierDefaults defs) {
    if (!defs.hasDefaultsForCheckedCode()) {
      throw new BugInCF(
          "GenericAnnotatedTypeFactory.createQualifierDefaults: "
              + "@DefaultQualifierInHierarchy or @DefaultFor(TypeUseLocation.OTHERWISE) not found. "
              + "Every checker must specify a default qualifier. "
              + getSortedQualifierNames());
    }

    // If a default unchecked code qualifier isn't specified, the defaults
    // for checked code will be used.
  }

  /**
   * Creates the {@link QualifierPolymorphism} instance which supports the QualifierPolymorphism
   * mechanism.
   *
   * @return the QualifierPolymorphism instance to use
   */
  protected QualifierPolymorphism createQualifierPolymorphism() {
    return new DefaultQualifierPolymorphism(processingEnv, this);
  }

  /**
   * Gives the current {@link QualifierPolymorphism} instance which supports the
   * QualifierPolymorphism mechanism.
   *
   * @return the QualifierPolymorphism instance to use
   */
  public QualifierPolymorphism getQualifierPolymorphism() {
    return this.poly;
  }

  // **********************************************************************
  // Factory Methods for the appropriate annotator classes
  // **********************************************************************

  @Override
  protected void postDirectSuperTypes(
      AnnotatedTypeMirror type, List<? extends AnnotatedTypeMirror> supertypes) {
    super.postDirectSuperTypes(type, supertypes);
    if (type.getKind() == TypeKind.DECLARED) {
      for (AnnotatedTypeMirror supertype : supertypes) {
        Element elt = ((DeclaredType) supertype.getUnderlyingType()).asElement();
        addComputedTypeAnnotations(elt, supertype);
      }
    }
  }

  /**
   * Gets the type of the resulting constructor call of a MemberReferenceTree.
   *
   * @param memberReferenceTree MemberReferenceTree where the member is a constructor
   * @param constructorType AnnotatedExecutableType of the declaration of the constructor
   * @return AnnotatedTypeMirror of the resulting type of the constructor
   */
  public AnnotatedTypeMirror getResultingTypeOfConstructorMemberReference(
      MemberReferenceTree memberReferenceTree, AnnotatedExecutableType constructorType) {
    assert memberReferenceTree.getMode() == MemberReferenceTree.ReferenceMode.NEW;

    // The return type for constructors should only have explicit annotations from the
    // constructor.  Recreate some of the logic from TypeFromTree.visitNewClass here.

    // The return type of the constructor will be the type of the expression of the member
    // reference tree.
    AnnotatedDeclaredType constructorReturnType =
        (AnnotatedDeclaredType) fromTypeTree(memberReferenceTree.getQualifierExpression());

    // Keep only explicit annotations and those from @Poly
    AnnotatedTypes.copyOnlyExplicitConstructorAnnotations(
        this, constructorReturnType, constructorType);

    // Now add back defaulting.
    addComputedTypeAnnotations(memberReferenceTree.getQualifierExpression(), constructorReturnType);
    return constructorReturnType;
  }

  /**
   * Returns the primary annotation on expression if it were evaluated at path.
   *
   * @param expression a Java expression
   * @param tree current tree
   * @param path location at which expression is evaluated
   * @param clazz class of the annotation
   * @return the annotation on expression or null if one does not exist
   * @throws JavaExpressionParseException thrown if the expression cannot be parsed
   */
  public AnnotationMirror getAnnotationFromJavaExpressionString(
      String expression, Tree tree, TreePath path, Class<? extends Annotation> clazz)
      throws JavaExpressionParseException {

    JavaExpression expressionObj = parseJavaExpressionString(expression, path);
    return getAnnotationFromJavaExpression(expressionObj, tree, clazz);
  }

  /**
   * Returns the primary annotation on an expression, at a particular location.
   *
   * @param expr the expression for which the annotation is returned
   * @param tree current tree
   * @param clazz the Class of the annotation
   * @return the annotation on expression or null if one does not exist
   */
  public AnnotationMirror getAnnotationFromJavaExpression(
      JavaExpression expr, Tree tree, Class<? extends Annotation> clazz) {
    return getAnnotationByClass(getAnnotationsFromJavaExpression(expr, tree), clazz);
  }

  /**
   * Returns the primary annotations on an expression, at a particular location.
   *
   * @param expr the expression for which the annotation is returned
   * @param tree current tree
   * @return the annotation on expression or null if one does not exist
   */
  public Set<AnnotationMirror> getAnnotationsFromJavaExpression(JavaExpression expr, Tree tree) {

    // Look in the store
    if (CFAbstractStore.canInsertJavaExpression(expr)) {
      Store store = getStoreBefore(tree);
      // `store` can be null if the tree is in a field initializer.
      if (store != null) {
        Value value = store.getValue(expr);
        if (value != null) {
          // Is it possible that this lacks some annotations that appear in the type factory?
          return value.getAnnotations();
        }
      }
    }

    // Look in the type factory, if not found in the store.
    if (expr instanceof LocalVariable) {
      Element ele = ((LocalVariable) expr).getElement();
      // Because of
      // https://github.com/eisop/checker-framework/issues/14
      // and the workaround in
      // org.checkerframework.framework.type.ElementAnnotationApplier.applyInternal
      // The annotationMirror may not contain all explicitly written annotations.
      return getAnnotatedType(ele).getAnnotations();
    } else if (expr instanceof FieldAccess) {
      Element ele = ((FieldAccess) expr).getField();
      return getAnnotatedType(ele).getAnnotations();
    } else {
      return Collections.emptySet();
    }
  }

  /**
   * Produces the JavaExpression as if {@code expression} were written at {@code currentPath}.
   *
   * @param expression a Java expression
   * @param currentPath the current path
   * @return the JavaExpression associated with expression on currentPath
   * @throws JavaExpressionParseException thrown if the expression cannot be parsed
   */
  public JavaExpression parseJavaExpressionString(String expression, TreePath currentPath)
      throws JavaExpressionParseException {

    return StringToJavaExpression.atPath(expression, currentPath, checker);
  }

  /**
   * Produces the JavaExpression and offset associated with an expression. For instance, "n+1" has
   * no associated JavaExpression, but this method produces a pair of a JavaExpression (for "n") and
   * an offset ("1").
   *
   * @param expression a Java expression, possibly with a constant offset
   * @param currentPath location at which expression is evaluated
   * @return the JavaExpression and offset for the given expression
   * @throws JavaExpressionParseException thrown if the expression cannot be parsed
   */
  public Pair<JavaExpression, String> getExpressionAndOffsetFromJavaExpressionString(
      String expression, TreePath currentPath) throws JavaExpressionParseException {
    Pair<String, String> p = getExpressionAndOffset(expression);
    JavaExpression r = parseJavaExpressionString(p.first, currentPath);
    return Pair.of(r, p.second);
  }

  /**
   * Returns the annotation mirror from dataflow for {@code expression}.
   *
   * <p>This will output a different annotation than {@link
   * #getAnnotationFromJavaExpressionString(String, Tree, TreePath, Class)}, because if the
   * specified annotation isn't found in the store, the type from the factory is used.
   *
   * @param expression a Java expression
   * @param tree the tree at the location to parse the expression
   * @param currentPath location at which expression is evaluated
   * @throws JavaExpressionParseException thrown if the expression cannot be parsed
   * @return an AnnotationMirror representing the type in the store at the given location from this
   *     type factory's type system, or null if one is not available
   */
  public AnnotationMirror getAnnotationMirrorFromJavaExpressionString(
      String expression, Tree tree, TreePath currentPath) throws JavaExpressionParseException {
    JavaExpression je = parseJavaExpressionString(expression, currentPath);
    if (je == null || !CFAbstractStore.canInsertJavaExpression(je)) {
      return null;
    }
    Store store = getStoreBefore(tree);
    Value value = store.getValue(je);
    return value != null ? value.getAnnotations().iterator().next() : null;
  }

  /**
   * Track the state of org.checkerframework.dataflow analysis scanning for each class tree in the
   * compilation unit.
   */
  protected enum ScanState {
    /** Dataflow analysis in progress. */
    IN_PROGRESS,
    /** Dataflow analysis finished. */
    FINISHED
  }

  /** Map from ClassTree to their dataflow analysis state. */
  protected final Map<ClassTree, ScanState> scannedClasses;

  /**
   * The result of the flow analysis. Invariant:
   *
   * <pre>
   *  scannedClasses.get(c) == FINISHED for some class c &rArr; flowResult != null
   * </pre>
   *
   * Note that flowResult contains analysis results for Trees from multiple classes which are
   * produced by multiple calls to performFlowAnalysis.
   */
  protected AnalysisResult<Value, Store> flowResult;

  /**
   * A mapping from methods (or other code blocks) to their regular exit store (used to check
   * postconditions).
   */
  protected IdentityHashMap<Tree, Store> regularExitStores;

  /** A mapping from methods (or other code blocks) to their exceptional exit store. */
  protected IdentityHashMap<Tree, Store> exceptionalExitStores;

  /** A mapping from methods to a list with all return statements and the corresponding store. */
  protected IdentityHashMap<MethodTree, List<Pair<ReturnNode, TransferResult<Value, Store>>>>
      returnStatementStores;

  /**
   * A mapping from methods to their a list with all return statements and the corresponding store.
   */
  protected IdentityHashMap<MethodInvocationTree, Store> methodInvocationStores;

  /**
   * Returns the regular exit store for a method or another code block (such as static
   * initializers).
   *
   * @param tree a MethodTree or other code block, such as a static initializer
   * @return the regular exit store, or {@code null}, if there is no such store (because the method
   *     cannot exit through the regular exit block).
   */
  public @Nullable Store getRegularExitStore(Tree tree) {
    return regularExitStores.get(tree);
  }

  /**
   * Returns the exceptional exit store for a method or another code block (such as static
   * initializers).
   *
   * @param tree a MethodTree or other code block, such as a static initializer
   * @return the exceptional exit store, or {@code null}, if there is no such store
   */
  public @Nullable Store getExceptionalExitStore(Tree tree) {
    return exceptionalExitStores.get(tree);
  }

  /**
   * Returns a list of all return statements of {@code method} paired with their corresponding
   * {@link TransferResult}. If {@code method} has no return statement, then the empty list is
   * returned.
   *
   * @param methodTree method whose return statements should be returned
   * @return a list of all return statements of {@code method} paired with their corresponding
   *     {@link TransferResult} or an empty list if {@code method} has no return statements
   */
  public List<Pair<ReturnNode, TransferResult<Value, Store>>> getReturnStatementStores(
      MethodTree methodTree) {
    assert returnStatementStores.containsKey(methodTree);
    return returnStatementStores.get(methodTree);
  }

  /**
   * Returns the store immediately before a given {@link Tree}.
   *
   * @return the store immediately before a given {@link Tree}
   */
  public Store getStoreBefore(Tree tree) {
    if (!analysis.isRunning()) {
      return flowResult.getStoreBefore(tree);
    }
    Set<Node> nodes = analysis.getNodesForTree(tree);
    if (nodes != null) {
      return getStoreBefore(nodes);
    } else {
      return flowResult.getStoreBefore(tree);
    }
  }

  /**
   * Returns the store immediately before a given Set of {@link Node}s.
   *
   * @return the store immediately before a given Set of {@link Node}s
   */
  public Store getStoreBefore(Set<Node> nodes) {
    Store merge = null;
    for (Node aNode : nodes) {
      Store s = getStoreBefore(aNode);
      if (merge == null) {
        merge = s;
      } else if (s != null) {
        merge = merge.leastUpperBound(s);
      }
    }
    return merge;
  }

  /**
   * Returns the store immediately before a given node.
   *
   * @param node a node whose pre-store to return
   * @return the store immediately before {@code node}
   */
  public Store getStoreBefore(Node node) {
    if (!analysis.isRunning()) {
      return flowResult.getStoreBefore(node);
    }
    TransferInput<Value, Store> prevStore = analysis.getInput(node.getBlock());
    if (prevStore == null) {
      return null;
    }
    Store store =
        AnalysisResult.runAnalysisFor(
            node,
            Analysis.BeforeOrAfter.BEFORE,
            prevStore,
            analysis.getNodeValues(),
            flowResultAnalysisCaches);
    return store;
  }

  /**
   * Returns the store immediately after a given tree.
   *
   * <p>May return null; for example, after a {@code return} statement.
   *
   * @param tree the tree whose post-store to return
   * @return the store immediately after a given tree
   */
  public Store getStoreAfter(Tree tree) {
    if (!analysis.isRunning()) {
      return flowResult.getStoreAfter(tree);
    }
    Set<Node> nodes = analysis.getNodesForTree(tree);
    return getStoreAfter(nodes);
  }

  /**
   * Returns the store immediately after a given set of nodes.
   *
   * @param nodes the nodes whose post-stores to LUB
   * @return the LUB of the stores store immediately after {@code nodes}
   */
  public Store getStoreAfter(Set<Node> nodes) {
    Store merge = null;
    for (Node node : nodes) {
      Store s = getStoreAfter(node);
      if (merge == null) {
        merge = s;
      } else if (s != null) {
        merge = merge.leastUpperBound(s);
      }
    }
    return merge;
  }

  /**
   * Returns the store immediately after a given {@link Node}.
   *
   * @param node node after which the store is returned
   * @return the store immediately after a given {@link Node}
   */
  public Store getStoreAfter(Node node) {
    if (!analysis.isRunning()) {
      return flowResult.getStoreAfter(node);
    }
    Store res =
        AnalysisResult.runAnalysisFor(
            node,
            Analysis.BeforeOrAfter.AFTER,
            analysis.getInput(node.getBlock()),
            analysis.getNodeValues(),
            flowResultAnalysisCaches);
    return res;
  }

  /**
   * See {@link org.checkerframework.dataflow.analysis.AnalysisResult#getNodesForTree(Tree)}.
   *
   * @return the {@link Node}s for a given {@link Tree}
   * @see org.checkerframework.dataflow.analysis.AnalysisResult#getNodesForTree(Tree)
   */
  public Set<Node> getNodesForTree(Tree tree) {
    return flowResult.getNodesForTree(tree);
  }

  /**
   * Return the first {@link Node} for a given {@link Tree} that has class {@code kind}.
   *
   * <p>You probably don't want to use this function: iterate over the result of {@link
   * #getNodesForTree(Tree)} yourself or ask for a conservative approximation of the store using
   * {@link #getStoreBefore(Tree)} or {@link #getStoreAfter(Tree)}. This method is for code that
   * uses a {@link Node} in a rather unusual way. Callers should probably be rewritten to not use a
   * {@link Node} at all.
   *
   * @param <T> the class of the node to return
   * @param tree a tree in which to search for a node of class {@code kind}
   * @param kind the class of the node to return
   * @return the first {@link Node} for a given {@link Tree} that has class {@code kind}
   * @see #getNodesForTree(Tree)
   * @see #getStoreBefore(Tree)
   * @see #getStoreAfter(Tree)
   */
  public <T extends Node> T getFirstNodeOfKindForTree(Tree tree, Class<T> kind) {
    Set<Node> nodes = getNodesForTree(tree);
    for (Node node : nodes) {
      if (node.getClass() == kind) {
        return kind.cast(node);
      }
    }
    return null;
  }

  /**
   * Returns the value of effectively final local variables.
   *
   * @return the value of effectively final local variables
   */
  public HashMap<Element, Value> getFinalLocalValues() {
    return flowResult.getFinalLocalValues();
  }

  /**
   * Perform a org.checkerframework.dataflow analysis over a single class tree and its nested
   * classes.
   *
   * @param classTree the class to analyze
   */
  protected void performFlowAnalysis(ClassTree classTree) {
    if (flowResult == null) {
      regularExitStores = new IdentityHashMap<>();
      exceptionalExitStores = new IdentityHashMap<>();
      returnStatementStores = new IdentityHashMap<>();
      flowResult = new AnalysisResult<>(flowResultAnalysisCaches);
    }

    // no need to scan annotations
    if (classTree.getKind() == Kind.ANNOTATION_TYPE) {
      // Mark finished so that default annotations will be applied.
      scannedClasses.put(classTree, ScanState.FINISHED);
      return;
    }

    Queue<Pair<ClassTree, Store>> queue = new ArrayDeque<>();
    List<Pair<VariableElement, Value>> fieldValues = new ArrayList<>();

    // No captured store for top-level classes.
    queue.add(Pair.of(classTree, null));

    while (!queue.isEmpty()) {
      final Pair<ClassTree, Store> qel = queue.remove();
      final ClassTree ct = qel.first;
      final Store capturedStore = qel.second;
      scannedClasses.put(ct, ScanState.IN_PROGRESS);

      TreePath preTreePath = visitorState.getPath();
      AnnotatedDeclaredType preClassType = visitorState.getClassType();
      ClassTree preClassTree = visitorState.getClassTree();
      AnnotatedDeclaredType preAMT = visitorState.getMethodReceiver();
      MethodTree preMT = visitorState.getMethodTree();

      // Don't use getPath, because that depends on the visitorState path.
      visitorState.setPath(TreePath.getPath(this.root, ct));
      visitorState.setClassType(getAnnotatedType(TreeUtils.elementFromDeclaration(ct)));
      visitorState.setClassTree(ct);
      visitorState.setMethodReceiver(null);
      visitorState.setMethodTree(null);

      // start with the captured store as initialization store
      initializationStaticStore = capturedStore;
      initializationStore = capturedStore;

      Queue<Pair<LambdaExpressionTree, Store>> lambdaQueue = new ArrayDeque<>();

      try {
        List<CFGMethod> methods = new ArrayList<>();
        for (Tree m : ct.getMembers()) {
          switch (m.getKind()) {
            case METHOD:
              MethodTree mt = (MethodTree) m;

              // Skip abstract and native methods because they have no body.
              Set<Modifier> flags = mt.getModifiers().getFlags();
              if (flags.contains(Modifier.ABSTRACT) || flags.contains(Modifier.NATIVE)) {
                break;
              }
              // Abstract methods in an interface have a null body but do not have an
              // ABSTRACT flag.
              if (mt.getBody() == null) {
                break;
              }

              // Wait with scanning the method until all other members
              // have been processed.
              CFGMethod met = new CFGMethod(mt, ct);
              methods.add(met);
              break;
            case VARIABLE:
              VariableTree vt = (VariableTree) m;
              ExpressionTree initializer = vt.getInitializer();
              // analyze initializer if present
              if (initializer != null) {
                boolean isStatic = vt.getModifiers().getFlags().contains(Modifier.STATIC);
                analyze(
                    queue,
                    lambdaQueue,
                    new CFGStatement(vt, ct),
                    fieldValues,
                    classTree,
                    true,
                    true,
                    isStatic,
                    capturedStore);
                Value value = flowResult.getValue(initializer);
                if (vt.getModifiers().getFlags().contains(Modifier.FINAL) && value != null) {
                  // Store the abstract value for the field.
                  VariableElement element = TreeUtils.elementFromDeclaration(vt);
                  fieldValues.add(Pair.of(element, value));
                }
              }
              break;
            case CLASS:
            case ANNOTATION_TYPE:
            case INTERFACE:
            case ENUM:
              // Visit inner and nested class trees.
              // TODO: Use no store for them? What can be captured?
              queue.add(Pair.of((ClassTree) m, capturedStore));
              break;
            case BLOCK:
              BlockTree b = (BlockTree) m;
              analyze(
                  queue,
                  lambdaQueue,
                  new CFGStatement(b, ct),
                  fieldValues,
                  ct,
                  true,
                  true,
                  b.isStatic(),
                  capturedStore);
              break;
            default:
              assert false : "Unexpected member: " + m.getKind();
              break;
          }
        }

        // Now analyze all methods.
        // TODO: at this point, we don't have any information about
        // fields of superclasses.
        for (CFGMethod met : methods) {
          analyze(
              queue,
              lambdaQueue,
              met,
              fieldValues,
              classTree,
              TreeUtils.isConstructor(met.getMethod()),
              false,
              false,
              capturedStore);
        }

        while (!lambdaQueue.isEmpty()) {
          Pair<LambdaExpressionTree, Store> lambdaPair = lambdaQueue.poll();
          MethodTree mt =
              (MethodTree) TreePathUtil.enclosingOfKind(getPath(lambdaPair.first), Kind.METHOD);
          analyze(
              queue,
              lambdaQueue,
              new CFGLambda(lambdaPair.first, classTree, mt),
              fieldValues,
              classTree,
              false,
              false,
              false,
              lambdaPair.second);
        }

        // by convention we store the static initialization store as the regular exit
        // store of the class node, so that it can later be used to check
        // that all fields are initialized properly.
        // see InitializationVisitor.visitClass
        if (initializationStaticStore == null) {
          regularExitStores.put(ct, emptyStore);
        } else {
          regularExitStores.put(ct, initializationStaticStore);
        }
      } finally {
        visitorState.setPath(preTreePath);
        visitorState.setClassType(preClassType);
        visitorState.setClassTree(preClassTree);
        visitorState.setMethodReceiver(preAMT);
        visitorState.setMethodTree(preMT);
      }

      scannedClasses.put(ct, ScanState.FINISHED);
    }
  }

  /**
   * Analyze the AST {@code ast} and store the result. Additional operations that should be
   * performed after analysis should be implemented in {@link #postAnalyze(ControlFlowGraph)}.
   *
   * @param queue the queue for encountered class trees and their initial stores
   * @param lambdaQueue the queue for encountered lambda expression trees and their initial stores
   * @param ast the AST to analyze
   * @param fieldValues the abstract values for all fields of the same class
   * @param currentClass the class we are currently looking at
   * @param isInitializationCode are we analyzing a (static/non-static) initializer block of a class
   * @param updateInitializationStore should the initialization store be updated
   * @param isStatic are we analyzing a static construct
   * @param capturedStore the input Store to use for captured variables, e.g. in a lambda
   * @see #postAnalyze(org.checkerframework.dataflow.cfg.ControlFlowGraph)
   */
  protected void analyze(
      Queue<Pair<ClassTree, Store>> queue,
      Queue<Pair<LambdaExpressionTree, Store>> lambdaQueue,
      UnderlyingAST ast,
      List<Pair<VariableElement, Value>> fieldValues,
      ClassTree currentClass,
      boolean isInitializationCode,
      boolean updateInitializationStore,
      boolean isStatic,
      Store capturedStore) {
    ControlFlowGraph cfg = CFCFGBuilder.build(root, ast, checker, this, processingEnv);

    if (isInitializationCode) {
      Store initStore = !isStatic ? initializationStore : initializationStaticStore;
      if (initStore != null) {
        // we have already seen initialization code and analyzed it, and
        // the analysis ended with the store initStore.
        // use it to start the next analysis.
        transfer.setFixedInitialStore(initStore);
      } else {
        transfer.setFixedInitialStore(capturedStore);
      }
    } else {
      transfer.setFixedInitialStore(capturedStore);
    }
    analysis.performAnalysis(cfg, fieldValues);
    AnalysisResult<Value, Store> result = analysis.getResult();

    // store result
    flowResult.combine(result);
    if (ast.getKind() == UnderlyingAST.Kind.METHOD) {
      // store exit store (for checking postconditions)
      CFGMethod mast = (CFGMethod) ast;
      MethodTree method = mast.getMethod();
      Store regularExitStore = analysis.getRegularExitStore();
      if (regularExitStore != null) {
        regularExitStores.put(method, regularExitStore);
      }
      Store exceptionalExitStore = analysis.getExceptionalExitStore();
      if (exceptionalExitStore != null) {
        exceptionalExitStores.put(method, exceptionalExitStore);
      }
      returnStatementStores.put(method, analysis.getReturnStatementStores());
    } else if (ast.getKind() == UnderlyingAST.Kind.ARBITRARY_CODE) {
      CFGStatement block = (CFGStatement) ast;
      Store regularExitStore = analysis.getRegularExitStore();
      if (regularExitStore != null) {
        regularExitStores.put(block.getCode(), regularExitStore);
      }
      Store exceptionalExitStore = analysis.getExceptionalExitStore();
      if (exceptionalExitStore != null) {
        exceptionalExitStores.put(block.getCode(), exceptionalExitStore);
      }
    } else if (ast.getKind() == UnderlyingAST.Kind.LAMBDA) {
      // TODO: Postconditions?

      CFGLambda block = (CFGLambda) ast;
      Store regularExitStore = analysis.getRegularExitStore();
      if (regularExitStore != null) {
        regularExitStores.put(block.getCode(), regularExitStore);
      }
      Store exceptionalExitStore = analysis.getExceptionalExitStore();
      if (exceptionalExitStore != null) {
        exceptionalExitStores.put(block.getCode(), exceptionalExitStore);
      }
    } else {
      assert false : "Unexpected AST kind: " + ast.getKind();
    }

    if (isInitializationCode && updateInitializationStore) {
      Store newInitStore = analysis.getRegularExitStore();
      if (!isStatic) {
        initializationStore = newInitStore;
      } else {
        initializationStaticStore = newInitStore;
      }
    }

    // add classes declared in CFG
    for (ClassTree cls : cfg.getDeclaredClasses()) {
      queue.add(Pair.of(cls, getStoreBefore(cls)));
    }
    // add lambdas declared in CFG
    for (LambdaExpressionTree lambda : cfg.getDeclaredLambdas()) {
      lambdaQueue.add(Pair.of(lambda, getStoreBefore(lambda)));
    }

    postAnalyze(cfg);
  }

  /**
   * Perform any additional operations on a CFG. Called once per CFG, after the CFG has been
   * analyzed by {@link #analyze(Queue, Queue, UnderlyingAST, List, ClassTree, boolean, boolean,
   * boolean, CFAbstractStore)}. This method can be used to initialize additional state or to
   * perform any analyses that are easier to perform on the CFG instead of the AST.
   *
   * @param cfg the CFG
   * @see #analyze(java.util.Queue, java.util.Queue,
   *     org.checkerframework.dataflow.cfg.UnderlyingAST, java.util.List,
   *     com.sun.source.tree.ClassTree, boolean, boolean, boolean,
   *     org.checkerframework.framework.flow.CFAbstractStore)
   */
  protected void postAnalyze(ControlFlowGraph cfg) {
    handleCFGViz(cfg);
  }

  /**
   * Handle the visualization of the CFG, if necessary.
   *
   * @param cfg the CFG
   */
  protected void handleCFGViz(ControlFlowGraph cfg) {
    if (checker.hasOption("flowdotdir") || checker.hasOption("cfgviz")) {
      getCFGVisualizer().visualize(cfg, cfg.getEntryBlock(), analysis);
    }
  }

  /**
   * Returns the type of the left-hand side of an assignment without applying local variable
   * defaults to type variables.
   *
   * <p>The type variables that are types of local variables are defaulted to top so that they can
   * be refined by dataflow. When these types are used as context during type argument inference,
   * this default is too conservative. So this method is used instead of {@link
   * GenericAnnotatedTypeFactory#getAnnotatedTypeLhs(Tree)}.
   *
   * <p>{@link TypeArgInferenceUtil#assignedToVariable(AnnotatedTypeFactory, Tree)} explains why a
   * different type is used.
   *
   * @param lhsTree left-hand side of an assignment
   * @return AnnotatedTypeMirror of {@code lhsTree}
   */
  public AnnotatedTypeMirror getAnnotatedTypeLhsNoTypeVarDefault(Tree lhsTree) {
    boolean old = this.shouldDefaultTypeVarLocals;
    shouldDefaultTypeVarLocals = false;
    AnnotatedTypeMirror type = getAnnotatedTypeLhs(lhsTree);
    this.shouldDefaultTypeVarLocals = old;
    return type;
  }

  /**
   * Returns the type of a left-hand side of an assignment.
   *
   * <p>The default implementation returns the type without considering dataflow type refinement.
   * Subclass can override this method and add additional logic for computing the type of a LHS.
   *
   * @param lhsTree left-hand side of an assignment
   * @return AnnotatedTypeMirror of {@code lhsTree}
   */
  public AnnotatedTypeMirror getAnnotatedTypeLhs(Tree lhsTree) {
    AnnotatedTypeMirror res;
    boolean oldUseFlow = useFlow;
    boolean oldShouldCache = shouldCache;
    useFlow = false;
    // Don't cache the result because getAnnotatedType(lhsTree) could
    // be called from elsewhere and would expect flow-sensitive type refinements.
    shouldCache = false;
    switch (lhsTree.getKind()) {
      case VARIABLE:
      case IDENTIFIER:
      case MEMBER_SELECT:
      case ARRAY_ACCESS:
        res = getAnnotatedType(lhsTree);
        break;
      case PARENTHESIZED:
        res = getAnnotatedTypeLhs(TreeUtils.withoutParens((ExpressionTree) lhsTree));
        break;
      default:
        if (TreeUtils.isTypeTree(lhsTree)) {
          // lhsTree is a type tree at the pseudo assignment of a returned expression to
          // declared return type.
          res = getAnnotatedType(lhsTree);
        } else {
          throw new BugInCF(
              "GenericAnnotatedTypeFactory: Unexpected tree passed to getAnnotatedTypeLhs. "
                  + "lhsTree: "
                  + lhsTree
                  + " Tree.Kind: "
                  + lhsTree.getKind());
        }
    }
    useFlow = oldUseFlow;
    shouldCache = oldShouldCache;
    return res;
  }

  /**
   * Returns the type of a varargs array of a method invocation or a constructor invocation. Returns
   * null only if private field {@code useFlow} is false.
   *
   * @param tree a method invocation or a constructor invocation
   * @return AnnotatedTypeMirror of varargs array for a method or constructor invocation {@code
   *     tree}; returns null if private field {@code useFlow} is false
   */
  public @Nullable AnnotatedTypeMirror getAnnotatedTypeVarargsArray(Tree tree) {
    if (!useFlow) {
      return null;
    }

    // Get the synthetic NewArray tree that dataflow creates as the last argument of a call to a
    // vararg method. Do this by getting the MethodInvocationNode to which "tree" maps. The last
    // argument node of the MethodInvocationNode stores the synthetic NewArray tree.
    List<Node> args;
    switch (tree.getKind()) {
      case METHOD_INVOCATION:
        args = getFirstNodeOfKindForTree(tree, MethodInvocationNode.class).getArguments();
        break;
      case NEW_CLASS:
        args = getFirstNodeOfKindForTree(tree, ObjectCreationNode.class).getArguments();
        break;
      default:
        throw new BugInCF("Unexpected kind of tree: " + tree);
    }

    assert !args.isEmpty() : "Arguments are empty";
    Node varargsArray = args.get(args.size() - 1);
    AnnotatedTypeMirror varargtype = getAnnotatedType(varargsArray.getTree());
    return varargtype;
  }

  /* Returns the type of a right-hand side of an assignment for unary operation like prefix or
   * postfix increment or decrement.
   *
   * @param tree unary operation tree for compound assignment
   * @return AnnotatedTypeMirror of a right-hand side of an assignment for unary operation
   */
  public AnnotatedTypeMirror getAnnotatedTypeRhsUnaryAssign(UnaryTree tree) {
    if (!useFlow) {
      return getAnnotatedType(tree);
    }
    AssignmentNode n = flowResult.getAssignForUnaryTree(tree);
    return getAnnotatedType(n.getExpression().getTree());
  }

  @Override
  public ParameterizedExecutableType constructorFromUse(NewClassTree tree) {
    ParameterizedExecutableType mType = super.constructorFromUse(tree);
    AnnotatedExecutableType method = mType.executableType;
    dependentTypesHelper.atConstructorInvocation(method, tree);
    return mType;
  }

  @Override
  protected void constructorFromUsePreSubstitution(
      NewClassTree tree, AnnotatedExecutableType type) {
    poly.resolve(tree, type);
  }

  @Override
  public AnnotatedTypeMirror getMethodReturnType(MethodTree m) {
    AnnotatedTypeMirror returnType = super.getMethodReturnType(m);
    dependentTypesHelper.atMethodBody(returnType, m);
    return returnType;
  }

  @Override
  public void addDefaultAnnotations(AnnotatedTypeMirror type) {
    addAnnotationsFromDefaultForType(null, type);
    typeAnnotator.visit(type, null);
    defaults.annotate((Element) null, type);
  }

  /**
   * This method is final; override {@link #addComputedTypeAnnotations(Tree, AnnotatedTypeMirror,
   * boolean)} instead.
   *
   * <p>{@inheritDoc}
   */
  @Override
  protected final void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) {
    addComputedTypeAnnotations(tree, type, this.useFlow);
  }

  /**
   * Like {@link #addComputedTypeAnnotations(Tree, AnnotatedTypeMirror)}. Overriding implementations
   * typically simply pass the boolean to calls to super.
   *
   * @param tree an AST node
   * @param type the type obtained from tree
   * @param iUseFlow whether to use information from dataflow analysis
   */
  protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, boolean iUseFlow) {
    if (root == null && ajavaTypes.isParsing()) {
      return;
    }
    assert root != null
        : "GenericAnnotatedTypeFactory.addComputedTypeAnnotations: "
            + " root needs to be set when used on trees; factory: "
            + this.getClass();

    String thisClass = null;
    String treeString = null;
    if (debug) {
      thisClass = this.getClass().getSimpleName();
      if (thisClass.endsWith("AnnotatedTypeFactory")) {
        thisClass = thisClass.substring(0, thisClass.length() - "AnnotatedTypeFactory".length());
      }
      treeString = TreeUtils.toStringTruncated(tree, 60);
    }
    log(
        "%s GATF.addComputedTypeAnnotations#1(%s, %s, %s)%n",
        thisClass, treeString, type, iUseFlow);
    if (!TreeUtils.isExpressionTree(tree)) {
      // Don't apply defaults to expressions. Their types may be computed from subexpressions
      // in treeAnnotator.
      addAnnotationsFromDefaultForType(TreeUtils.elementFromTree(tree), type);
      log("%s GATF.addComputedTypeAnnotations#2(%s, %s)%n", thisClass, treeString, type);
    }
    applyQualifierParameterDefaults(tree, type);
    log("%s GATF.addComputedTypeAnnotations#3(%s, %s)%n", thisClass, treeString, type);
    treeAnnotator.visit(tree, type);
    log("%s GATF.addComputedTypeAnnotations#4(%s, %s)%n", thisClass, treeString, type);
    if (TreeUtils.isExpressionTree(tree)) {
      // If a tree annotator, did not add a type, add the DefaultForUse default.
      addAnnotationsFromDefaultForType(TreeUtils.elementFromTree(tree), type);
      log("%s GATF.addComputedTypeAnnotations#5(%s, %s)%n", thisClass, treeString, type);
    }
    typeAnnotator.visit(type, null);
    log("%s GATF.addComputedTypeAnnotations#6(%s, %s)%n", thisClass, treeString, type);
    defaults.annotate(tree, type);
    log("%s GATF.addComputedTypeAnnotations#7(%s, %s)%n", thisClass, treeString, type);

    if (iUseFlow) {
      Value as = getInferredValueFor(tree);
      if (as != null) {
        applyInferredAnnotations(type, as);
        log(
            "%s GATF.addComputedTypeAnnotations#8(%s, %s), as=%s%n",
            thisClass, treeString, type, as);
      }
    }
    log(
        "%s GATF.addComputedTypeAnnotations#9(%s, %s, %s) done%n",
        thisClass, treeString, type, iUseFlow);
  }

  /**
   * Flow analysis will be performed if all of the following are true.
   *
   * <ul>
   *   <li>tree is a {@link ClassTree}
   *   <li>Flow analysis has not already been performed on tree
   * </ul>
   *
   * @param tree the tree to check and possibly perform flow analysis on
   */
  protected void checkAndPerformFlowAnalysis(Tree tree) {
    // For performance reasons, we require that getAnnotatedType is called
    // on the ClassTree before it's called on any code contained in the class,
    // so that we can perform flow analysis on the class.  Previously we
    // used TreePath.getPath to find enclosing classes, but that call
    // alone consumed more than 10% of execution time.  See BaseTypeVisitor
    // .visitClass for the call to getAnnotatedType that triggers analysis.
    if (tree instanceof ClassTree) {
      ClassTree classTree = (ClassTree) tree;
      if (!scannedClasses.containsKey(classTree)) {
        performFlowAnalysis(classTree);
      }
    }
  }

  /**
   * Returns the inferred value (by the org.checkerframework.dataflow analysis) for a given tree.
   */
  public Value getInferredValueFor(Tree tree) {
    if (tree == null) {
      throw new BugInCF("GenericAnnotatedTypeFactory.getInferredValueFor called with null tree");
    }
    Value as = null;
    if (analysis.isRunning()) {
      as = analysis.getValue(tree);
    }
    if (as == null) {
      as = flowResult.getValue(tree);
    }
    return as;
  }

  /**
   * Applies the annotations inferred by the org.checkerframework.dataflow analysis to the type
   * {@code type}.
   */
  protected void applyInferredAnnotations(AnnotatedTypeMirror type, Value as) {
    DefaultInferredTypesApplier applier =
        new DefaultInferredTypesApplier(getQualifierHierarchy(), this);
    applier.applyInferredType(type, as.getAnnotations(), as.getUnderlyingType());
  }

  /**
   * Applies defaults for types in a class with an qualifier parameter.
   *
   * <p>Within a class with {@code @HasQualifierParameter}, types with that class default to the
   * polymorphic qualifier rather than the typical default. Local variables with a type that has a
   * qualifier parameter are initialized to the type of their initializer, rather than the default
   * for local variables.
   *
   * @param tree a Tree whose type is {@code type}
   * @param type where the defaults are applied
   */
  protected void applyQualifierParameterDefaults(Tree tree, AnnotatedTypeMirror type) {
    applyQualifierParameterDefaults(TreeUtils.elementFromTree(tree), type);
  }

  /**
   * Applies defaults for types in a class with an qualifier parameter.
   *
   * <p>Within a class with {@code @HasQualifierParameter}, types with that class default to the
   * polymorphic qualifier rather than the typical default. Local variables with a type that has a
   * qualifier parameter are initialized to the type of their initializer, rather than the default
   * for local variables.
   *
   * @param elt an Element whose type is {@code type}
   * @param type where the defaults are applied
   */
  protected void applyQualifierParameterDefaults(@Nullable Element elt, AnnotatedTypeMirror type) {
    if (elt == null) {
      return;
    }
    switch (elt.getKind()) {
      case CONSTRUCTOR:
      case METHOD:
      case FIELD:
      case LOCAL_VARIABLE:
      case PARAMETER:
        break;
      default:
        return;
    }

    applyLocalVariableQualifierParameterDefaults(elt, type);

    TypeElement enclosingClass = ElementUtils.enclosingTypeElement(elt);
    Set<AnnotationMirror> tops;
    if (enclosingClass != null) {
      tops = getQualifierParameterHierarchies(enclosingClass);
    } else {
      return;
    }
    if (tops.isEmpty()) {
      return;
    }
    Set<AnnotationMirror> polyWithQualParam = AnnotationUtils.createAnnotationSet();
    for (AnnotationMirror top : tops) {
      AnnotationMirror poly = qualHierarchy.getPolymorphicAnnotation(top);
      if (poly != null) {
        polyWithQualParam.add(poly);
      }
    }
    new TypeAnnotator(this) {
      @Override
      public Void visitDeclared(AnnotatedDeclaredType type, Void aVoid) {
        if (type.getUnderlyingType().asElement().equals(enclosingClass)) {
          type.addMissingAnnotations(polyWithQualParam);
        }
        return super.visitDeclared(type, aVoid);
      }
    }.visit(type);
  }

  /**
   * Defaults local variables with types that have a qualifier parameter to the type of their
   * initializer, if an initializer is present. Does nothing for local variables with no
   * initializer.
   *
   * @param elt an Element whose type is {@code type}
   * @param type where the defaults are applied
   */
  private void applyLocalVariableQualifierParameterDefaults(Element elt, AnnotatedTypeMirror type) {
    if (elt.getKind() != ElementKind.LOCAL_VARIABLE
        || getQualifierParameterHierarchies(type).isEmpty()
        || variablesUnderInitialization.contains(elt)) {
      return;
    }

    Tree declTree = declarationFromElement(elt);
    if (declTree == null || declTree.getKind() != Kind.VARIABLE) {
      return;
    }

    ExpressionTree initializer = ((VariableTree) declTree).getInitializer();
    if (initializer == null) {
      return;
    }

    VariableElement variableElt = (VariableElement) elt;
    variablesUnderInitialization.add(variableElt);
    AnnotatedTypeMirror initializerType;
    if (shouldCache && initializerCache.containsKey(initializer)) {
      initializerType = initializerCache.get(initializer);
    } else {
      // When this method is called by getAnnotatedTypeLhs, flow is turned off.
      // Turn it back on so the type of the initializer is the refined type.
      boolean oldUseFlow = useFlow;
      useFlow = everUseFlow;
      try {
        initializerType = getAnnotatedType(initializer);
      } finally {
        useFlow = oldUseFlow;
      }
    }

    Set<AnnotationMirror> qualParamTypes = AnnotationUtils.createAnnotationSet();
    for (AnnotationMirror initializerAnnotation : initializerType.getAnnotations()) {
      if (hasQualifierParameterInHierarchy(
          type, qualHierarchy.getTopAnnotation(initializerAnnotation))) {
        qualParamTypes.add(initializerAnnotation);
      }
    }

    type.addMissingAnnotations(qualParamTypes);
    variablesUnderInitialization.remove(variableElt);
    if (shouldCache) {
      initializerCache.put(initializer, initializerType);
    }
  }

  /**
   * To add annotations to the type of method or constructor parameters, add a {@link TypeAnnotator}
   * using {@link #createTypeAnnotator()} and see the comment in {@link
   * TypeAnnotator#visitExecutable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType,
   * Void)}.
   *
   * @param elt an element
   * @param type the type obtained from {@code elt}
   */
  @Override
  public void addComputedTypeAnnotations(Element elt, AnnotatedTypeMirror type) {
    addAnnotationsFromDefaultForType(elt, type);
    applyQualifierParameterDefaults(elt, type);
    typeAnnotator.visit(type, null);
    defaults.annotate(elt, type);
    dependentTypesHelper.atLocalVariable(type, elt);
  }

  @Override
  public ParameterizedExecutableType methodFromUse(MethodInvocationTree tree) {
    ParameterizedExecutableType mType = super.methodFromUse(tree);
    AnnotatedExecutableType method = mType.executableType;
    dependentTypesHelper.atMethodInvocation(method, tree);
    return mType;
  }

  @Override
  public void methodFromUsePreSubstitution(ExpressionTree tree, AnnotatedExecutableType type) {
    super.methodFromUsePreSubstitution(tree, type);
    if (tree instanceof MethodInvocationTree) {
      poly.resolve((MethodInvocationTree) tree, type);
    }
  }

  @Override
  public List<AnnotatedTypeParameterBounds> typeVariablesFromUse(
      AnnotatedDeclaredType type, TypeElement element) {
    List<AnnotatedTypeParameterBounds> f = super.typeVariablesFromUse(type, element);
    dependentTypesHelper.atParameterizedTypeUse(f, element);
    return f;
  }

  /**
   * Returns the empty store.
   *
   * @return the empty store
   */
  public Store getEmptyStore() {
    return emptyStore;
  }

  /**
   * Returns the AnnotatedTypeFactory of the subchecker and copies the current visitor state to the
   * sub-factory so that the types are computed properly. Because the visitor state is copied, call
   * this method each time a subfactory is needed rather than store the returned subfactory in a
   * field.
   *
   * @see BaseTypeChecker#getTypeFactoryOfSubchecker(Class)
   */
  @SuppressWarnings("TypeParameterUnusedInFormals") // Intentional abuse
  public <T extends GenericAnnotatedTypeFactory<?, ?, ?, ?>, U extends BaseTypeChecker>
      T getTypeFactoryOfSubchecker(Class<U> checkerClass) {
    T subFactory = checker.getTypeFactoryOfSubchecker(checkerClass);
    if (subFactory != null && subFactory.getVisitorState() != null) {
      // Copy the visitor state so that the types are computed properly.
      VisitorState subFactoryVisitorState = subFactory.getVisitorState();
      subFactoryVisitorState.setPath(visitorState.getPath());
      subFactoryVisitorState.setClassTree(visitorState.getClassTree());
      subFactoryVisitorState.setClassType(visitorState.getClassType());
      subFactoryVisitorState.setMethodTree(visitorState.getMethodTree());
      subFactoryVisitorState.setMethodReceiver(visitorState.getMethodReceiver());
    }
    return subFactory;
  }

  /**
   * Should the local variable default annotation be applied to type variables?
   *
   * <p>It is initialized to true if data flow is used by the checker. It is set to false when
   * getting the assignment context for type argument inference.
   *
   * @see GenericAnnotatedTypeFactory#getAnnotatedTypeLhsNoTypeVarDefault
   * @return shouldDefaultTypeVarLocals
   */
  public boolean getShouldDefaultTypeVarLocals() {
    return shouldDefaultTypeVarLocals;
  }

  /** The CFGVisualizer to be used by all CFAbstractAnalysis instances. */
  protected final CFGVisualizer<Value, Store, TransferFunction> cfgVisualizer;

  /**
   * Create a new CFGVisualizer.
   *
   * @return a new CFGVisualizer, or null if none will be used on this run
   */
  protected @Nullable CFGVisualizer<Value, Store, TransferFunction> createCFGVisualizer() {
    if (checker.hasOption("flowdotdir")) {
      String flowdotdir = checker.getOption("flowdotdir");
      if (flowdotdir.equals("")) {
        throw new UserError("Emtpy string provided for -Aflowdotdir command-line argument");
      }
      boolean verbose = checker.hasOption("verbosecfg");

      Map<String, Object> args = new HashMap<>(2);
      args.put("outdir", flowdotdir);
      args.put("verbose", verbose);
      args.put("checkerName", getCheckerName());

      CFGVisualizer<Value, Store, TransferFunction> res = new DOTCFGVisualizer<>();
      res.init(args);
      return res;
    } else if (checker.hasOption("cfgviz")) {
      String cfgviz = checker.getOption("cfgviz");
      if (cfgviz == null) {
        throw new UserError(
            "-Acfgviz specified without arguments, should be -Acfgviz=VizClassName[,opts,...]");
      }
      String[] opts = cfgviz.split(",");
      String vizClassName = opts[0];
      if (!Signatures.isBinaryName(vizClassName)) {
        throw new UserError(
            "Bad -Acfgviz class name \"%s\", should be a binary name.", vizClassName);
      }

      Map<String, Object> args = processCFGVisualizerOption(opts);
      if (!args.containsKey("verbose")) {
        boolean verbose = checker.hasOption("verbosecfg");
        args.put("verbose", verbose);
      }
      args.put("checkerName", getCheckerName());

      CFGVisualizer<Value, Store, TransferFunction> res =
          BaseTypeChecker.invokeConstructorFor(vizClassName, null, null);
      res.init(args);
      return res;
    }
    // Nobody expected to use cfgVisualizer if neither option given.
    return null;
  }

  /** A simple utility method to determine a short checker name to be used by CFG visualizations. */
  private String getCheckerName() {
    String checkerName = checker.getClass().getSimpleName();
    if (checkerName.endsWith("Checker")) {
      checkerName = checkerName.substring(0, checkerName.length() - "Checker".length());
    } else if (checkerName.endsWith("Subchecker")) {
      checkerName = checkerName.substring(0, checkerName.length() - "Subchecker".length());
    }
    return checkerName;
  }

  /**
   * Parse keys or key-value pairs into a map from key to value (to true if no value is provided).
   *
   * @param opts the CFG visualization options
   * @return a map that represents the options
   */
  private Map<String, Object> processCFGVisualizerOption(String[] opts) {
    Map<String, Object> res = new HashMap<>(opts.length - 1);
    // Index 0 is the visualizer class name and can be ignored.
    for (int i = 1; i < opts.length; ++i) {
      String opt = opts[i];
      String[] split = opt.split("=");
      switch (split.length) {
        case 1:
          res.put(split[0], true);
          break;
        case 2:
          res.put(split[0], split[1]);
          break;
        default:
          throw new UserError("Too many '=' in cfgviz option: " + opt);
      }
    }
    return res;
  }

  /** The CFGVisualizer to be used by all CFAbstractAnalysis instances. */
  public CFGVisualizer<Value, Store, TransferFunction> getCFGVisualizer() {
    return cfgVisualizer;
  }

  @Override
  public void postAsMemberOf(AnnotatedTypeMirror type, AnnotatedTypeMirror owner, Element element) {
    super.postAsMemberOf(type, owner, element);
    if (element.getKind() == ElementKind.FIELD) {
      poly.resolve(((VariableElement) element), owner, type);
    }
  }

  /**
   * Adds default qualifiers based on the underlying type of {@code type} to {@code type}. If {@code
   * element} is a local variable, then the defaults are not added.
   *
   * <p>(This uses both the {@link DefaultQualifierForUseTypeAnnotator} and {@link
   * DefaultForTypeAnnotator}.)
   *
   * @param element possibly null element whose type is {@code type}
   * @param type the type to which defaults are added
   */
  protected void addAnnotationsFromDefaultForType(
      @Nullable Element element, AnnotatedTypeMirror type) {
    if (element != null && element.getKind() == ElementKind.LOCAL_VARIABLE) {
      if (type.getKind() == TypeKind.DECLARED) {
        // If this is a type for a local variable, don't apply the default to the primary location.
        AnnotatedDeclaredType declaredType = (AnnotatedDeclaredType) type;
        if (declaredType.getEnclosingType() != null) {
          defaultQualifierForUseTypeAnnotator.visit(declaredType.getEnclosingType());
          defaultForTypeAnnotator.visit(declaredType.getEnclosingType());
        }
        for (AnnotatedTypeMirror typeArg : declaredType.getTypeArguments()) {
          defaultQualifierForUseTypeAnnotator.visit(typeArg);
          defaultForTypeAnnotator.visit(typeArg);
        }
      } else if (type.getKind().isPrimitive()) {
        // Don't apply the default for local variables with primitive types.
      } else {
        defaultQualifierForUseTypeAnnotator.visit(type);
        defaultForTypeAnnotator.visit(type);
      }
    } else {
      defaultQualifierForUseTypeAnnotator.visit(type);
      defaultForTypeAnnotator.visit(type);
    }
  }

  // You can change this temporarily to produce verbose logs.
  /** Whether to output verbose, low-level debugging messages. */
  private static final boolean debug = false;

  /**
   * Output a message, if logging is on.
   *
   * @param format a format string
   * @param args arguments to the format string
   */
  @FormatMethod
  private static void log(String format, Object... args) {
    if (debug) {
      SystemPlume.sleep(1); // logging can interleave with typechecker output
      System.out.printf(format, args);
    }
  }

  /**
   * Cache of types found that are relevantTypes or subclass of supported types. Used so that
   * isSubtype doesn't need to be called repeatedly on the same types.
   */
  private Map<TypeMirror, Boolean> allFoundRelevantTypes = CollectionUtils.createLRUCache(300);

  /**
   * Returns true if users can write type annotations from this type system on the given Java type.
   *
   * @param tm a type
   * @return true if users can write type annotations from this type system on the given Java type
   */
  public boolean isRelevant(TypeMirror tm) {
    tm = types.erasure(tm);
    Boolean cachedResult = allFoundRelevantTypes.get(tm);
    if (cachedResult != null) {
      return cachedResult;
    }
    boolean result = isRelevantHelper(tm);
    allFoundRelevantTypes.put(tm, result);
    return result;
  }

  /**
   * Returns true if users can write type annotations from this type system on the given Java type.
   * Does not use a cache. Is a helper method for {@link #isRelevant}.
   *
   * @param tm a type
   * @return true if users can write type annotations from this type system on the given Java type
   */
  private boolean isRelevantHelper(TypeMirror tm) {

    if (relevantJavaTypes.contains(tm)) {
      return true;
    }

    switch (tm.getKind()) {

        // Primitives have no subtyping relationships, but the lookup might have failed
        // because tm has metadata such as annotations.
      case BOOLEAN:
      case BYTE:
      case CHAR:
      case DOUBLE:
      case FLOAT:
      case INT:
      case LONG:
      case SHORT:
        for (TypeMirror relevantJavaType : relevantJavaTypes) {
          if (types.isSameType(tm, relevantJavaType)) {
            return true;
          }
        }
        return false;

        // Void is never relevant
      case VOID:
        return false;

      case ARRAY:
        return arraysAreRelevant;

      case DECLARED:
        for (TypeMirror relevantJavaType : relevantJavaTypes) {
          if (types.isSubtype(relevantJavaType, tm) || types.isSubtype(tm, relevantJavaType)) {
            return true;
          }
        }
        return false;

      case TYPEVAR:
        return isRelevant(((TypeVariable) tm).getUpperBound());

      default:
        throw new BugInCF("isRelevantHelper(%s): Unexpected TypeKind %s", tm, tm.getKind());
    }
  }

  /**
   * Return the type of the default value of the given type. The default value is 0, false, or null.
   *
   * @param typeMirror a type
   * @return the annotated type of {@code type}'s default value
   */
  // TODO: Cache results to avoid recomputation.
  public AnnotatedTypeMirror getDefaultValueAnnotatedType(TypeMirror typeMirror) {
    AnnotatedTypeMirror defaultValue = AnnotatedTypeMirror.createType(typeMirror, this, false);
    addComputedTypeAnnotations(
        TreeUtils.getDefaultValueTree(typeMirror, processingEnv), defaultValue, false);
    return defaultValue;
  }

  /**
   * Return the contract annotations (that is, pre- and post-conditions) for the given AMethod. Does
   * not modify the AMethod. This method must only be called when using WholeProgramInferenceScenes.
   *
   * @param m AFU representation of a method
   * @return contract annotations for the method
   */
  public List<AnnotationMirror> getContractAnnotations(AMethod m) {
    List<AnnotationMirror> preconds = getPreconditionAnnotations(m);
    List<AnnotationMirror> postconds = getPostconditionAnnotations(m, preconds);
    List<AnnotationMirror> result = preconds;
    result.addAll(postconds);
    return result;
  }

  /**
   * Return the precondition annotations for the given AMethod. Does not modify the AMethod. This
   * method must only be called when using WholeProgramInferenceScenes.
   *
   * @param m AFU representation of a method
   * @return precondition annotations for the method
   */
  public List<AnnotationMirror> getPreconditionAnnotations(AMethod m) {
    List<AnnotationMirror> result = new ArrayList<>(m.getPreconditions().size());
    for (Map.Entry<VariableElement, AField> entry : m.getPreconditions().entrySet()) {
      WholeProgramInferenceImplementation<?> wholeProgramInference =
          (WholeProgramInferenceImplementation<?>) getWholeProgramInference();
      WholeProgramInferenceScenesStorage storage =
          (WholeProgramInferenceScenesStorage) wholeProgramInference.getStorage();
      TypeMirror typeMirror = entry.getKey().asType();
      AnnotatedTypeMirror inferredType =
          storage.atmFromStorageLocation(typeMirror, entry.getValue().type);
      result.addAll(getPreconditionAnnotation(entry.getKey(), inferredType));
    }
    Collections.sort(result, Ordering.usingToString());
    return result;
  }

  /**
   * Return the postcondition annotations for the given AMethod. Does not modify the AMethod. This
   * method must only be called when using WholeProgramInferenceScenes.
   *
   * @param m AFU representation of a method
   * @param preconds the precondition annotations for the method; used to suppress redundant
   *     postconditions
   * @return postcondition annotations for the method
   */
  public List<AnnotationMirror> getPostconditionAnnotations(
      AMethod m, List<AnnotationMirror> preconds) {
    List<AnnotationMirror> result = new ArrayList<>(m.getPostconditions().size());
    for (Map.Entry<VariableElement, AField> entry : m.getPostconditions().entrySet()) {
      WholeProgramInferenceImplementation<?> wholeProgramInference =
          (WholeProgramInferenceImplementation<?>) getWholeProgramInference();
      WholeProgramInferenceScenesStorage storage =
          (WholeProgramInferenceScenesStorage) wholeProgramInference.getStorage();
      TypeMirror typeMirror = entry.getKey().asType();
      AnnotatedTypeMirror inferredType =
          storage.atmFromStorageLocation(typeMirror, entry.getValue().type);
      result.addAll(getPostconditionAnnotation(entry.getKey(), inferredType, preconds));
    }
    Collections.sort(result, Ordering.usingToString());
    return result;
  }

  /**
   * Return the contract annotations (that is, pre- and post-conditions) for the given
   * CallableDeclarationAnnos. Does not modify the CallableDeclarationAnnos.
   *
   * @param methodAnnos annotation data for a method
   * @return contract annotations for the method
   */
  public List<AnnotationMirror> getContractAnnotations(
      WholeProgramInferenceJavaParserStorage.CallableDeclarationAnnos methodAnnos) {
    List<AnnotationMirror> preconds = getPreconditionAnnotations(methodAnnos);
    List<AnnotationMirror> postconds = getPostconditionAnnotations(methodAnnos, preconds);
    List<AnnotationMirror> result = preconds;
    result.addAll(postconds);
    return result;
  }

  /**
   * Return the precondition annotations for the given CallableDeclarationAnnos. Does not modify the
   * CallableDeclarationAnnos.
   *
   * @param methodAnnos annotation data for a method
   * @return precondition annotations for the method
   */
  public List<AnnotationMirror> getPreconditionAnnotations(
      WholeProgramInferenceJavaParserStorage.CallableDeclarationAnnos methodAnnos) {
    List<AnnotationMirror> result = new ArrayList<>();
    for (Map.Entry<VariableElement, AnnotatedTypeMirror> entry :
        methodAnnos.getFieldToPreconditions().entrySet()) {
      result.addAll(getPreconditionAnnotation(entry.getKey(), entry.getValue()));
    }
    Collections.sort(result, Ordering.usingToString());
    return result;
  }

  /**
   * Return the postcondition annotations for the given CallableDeclarationAnnos. Does not modify
   * the CallableDeclarationAnnos.
   *
   * @param methodAnnos annotation data for a method
   * @param preconds the precondition annotations for the method; used to suppress redundant
   *     postconditions
   * @return postcondition annotations for the method
   */
  public List<AnnotationMirror> getPostconditionAnnotations(
      WholeProgramInferenceJavaParserStorage.CallableDeclarationAnnos methodAnnos,
      List<AnnotationMirror> preconds) {
    List<AnnotationMirror> result = new ArrayList<>();
    for (Map.Entry<VariableElement, AnnotatedTypeMirror> entry :
        methodAnnos.getFieldToPostconditions().entrySet()) {
      result.addAll(getPostconditionAnnotation(entry.getKey(), entry.getValue(), preconds));
    }
    Collections.sort(result, Ordering.usingToString());
    return result;
  }

  /**
   * Return a list of precondition annotations for the given field. Returns an empty list if none
   * can be created, because the qualifier has elements/arguments, which {@code @RequiresQualifier}
   * does not support.
   *
   * <p>This is of the form {@code @RequiresQualifier(expression="this.elt",
   * qualifier=MyQual.class)} when elt is declared as {@code @A} or {@code @Poly*} and f contains
   * {@code @B} which is a sub-qualifier of {@code @A}.
   *
   * @param elt element for a field, which is declared in the same class as the method
   * @param inferredType the type of the field, on method entry
   * @return precondition annotations for the element (possibly an empty list)
   */
  public List<AnnotationMirror> getPreconditionAnnotation(
      VariableElement elt, AnnotatedTypeMirror inferredType) {
    return getPreOrPostconditionAnnotation(elt, inferredType, BeforeOrAfter.BEFORE, null);
  }

  /**
   * Returns an {@code @EnsuresQualifier} annotation for the given field. Returns an empty list if
   * none can be created, because the qualifier has elements/arguments, which
   * {@code @EnsuresQualifier} does not support.
   *
   * <p>This implementation makes no assumptions about preconditions suppressing postconditions, but
   * subclasses may do so.
   *
   * <p>This is of the form {@code @EnsuresQualifier(expression="this.elt", qualifier=MyQual.class)}
   * when elt is declared as {@code @A} or {@code @Poly*} and f contains {@code @B} which is a
   * sub-qualifier of {@code @A}.
   *
   * @param elt element for a field
   * @param inferredType the type of the field, on method exit
   * @param preconds the precondition annotations for the method; used to suppress redundant
   *     postconditions
   * @return postcondition annotations for the element (possibly an empty list)
   */
  public List<AnnotationMirror> getPostconditionAnnotation(
      VariableElement elt, AnnotatedTypeMirror inferredType, List<AnnotationMirror> preconds) {
    return getPreOrPostconditionAnnotation(elt, inferredType, BeforeOrAfter.AFTER, preconds);
  }

  /**
   * Helper method for {@link #getPreconditionAnnotation} and {@link #getPostconditionAnnotation}.
   *
   * <p>Returns a {@code @RequiresQualifier} or {@code @EnsuresQualifier} annotation for the given
   * field. Returns an empty list if none can be created, because the qualifier has
   * elements/arguments, which {@code @RequiresQualifier} and {@code @EnsuresQualifier} do not
   * support.
   *
   * <p>This implementation makes no assumptions about preconditions suppressing postconditions, but
   * subclasses may do so.
   *
   * @param elt element for a field
   * @param inferredType the type of the field, on method entry or exit (depending on the value of
   *     {@code preOrPost})
   * @param preOrPost whether to return preconditions or postconditions
   * @param preconds the precondition annotations for the method; used to suppress redundant
   *     postconditions; non-null exactly when {@code preOrPost} is {@code AFTER}
   * @return precondition or postcondition annotations for the element (possibly an empty list)
   */
  protected List<AnnotationMirror> getPreOrPostconditionAnnotation(
      VariableElement elt,
      AnnotatedTypeMirror inferredType,
      Analysis.BeforeOrAfter preOrPost,
      @Nullable List<AnnotationMirror> preconds) {
    assert (preOrPost == BeforeOrAfter.BEFORE) == (preconds == null);

    if (getWholeProgramInference() == null) {
      return Collections.emptyList();
    }

    AnnotatedTypeMirror declaredType = fromElement(elt);

    // TODO: should this only check the top-level annotations?
    if (declaredType.equals(inferredType)) {
      return Collections.emptyList();
    }

    List<AnnotationMirror> result = new ArrayList<AnnotationMirror>();
    for (AnnotationMirror inferredAm : inferredType.getAnnotations()) {
      AnnotationMirror declaredAm = declaredType.getAnnotationInHierarchy(inferredAm);
      if (declaredAm == null && declaredType.getKind() != TypeKind.TYPEVAR) {
        // There is no explicitly-written annotation for the given qualifier hierarchy.
        // Determine the default.
        addComputedTypeAnnotations(elt, declaredType);
        declaredAm = declaredType.getAnnotationInHierarchy(inferredAm);
        if (declaredAm == null) {
          throw new BugInCF(
              "getPreOrPostconditionAnnotation(%s, %s): no defaulted annotation%n  declaredType=%s"
                  + "  [%s %s]%n  inferredType=%s  [%s %s]%n",
              elt,
              inferredType,
              declaredType.toString(true),
              declaredType.getKind(),
              declaredType.getClass(),
              inferredType.toString(true),
              inferredType.getKind(),
              inferredType.getClass());
        }
      }

      if (declaredAm == null || AnnotationUtils.areSame(inferredAm, declaredAm)) {
        continue;
      }
      // inferredAm must be a subtype of declaredAm (since they are not equal).
      AnnotationMirror anno = requiresOrEnsuresQualifierAnno(elt, inferredAm, preOrPost);
      if (anno != null) {
        result.add(anno);
      }
    }

    return result;
  }

  /**
   * Returns a {@code RequiresQualifier("...")} or {@code EnsuresQualifier("...")} annotation for
   * the given field. Returns null if none can be created, because the qualifier has
   * elements/arguments, which {@code @RequiresQualifier} and {@code @EnsuresQualifier} do not
   * support.
   *
   * <p>This is of the form {@code @RequiresQualifier(expression="this.elt",
   * qualifier=MyQual.class)} or {@code @EnsuresQualifier(expression="this.elt",
   * qualifier=MyQual.class)} when elt is declared as {@code @A} or {@code @Poly*} and f contains
   * {@code @B} which is a sub-qualifier of {@code @A}.
   *
   * @param fieldElement a field
   * @param qualifier the qualifier that must be present
   * @param preOrPost whether to return a precondition or postcondition annotation
   * @return a {@code RequiresQualifier("...")} or {@code EnsuresQualifier("...")} annotation for
   *     the given field, or null
   */
  protected @Nullable AnnotationMirror requiresOrEnsuresQualifierAnno(
      VariableElement fieldElement, AnnotationMirror qualifier, Analysis.BeforeOrAfter preOrPost) {
    if (!qualifier.getElementValues().isEmpty()) {
      // @RequiresQualifier does not yet support annotations with elements/arguments.
      return null;
    }

    AnnotationBuilder builder =
        new AnnotationBuilder(
            processingEnv,
            preOrPost == BeforeOrAfter.BEFORE ? RequiresQualifier.class : EnsuresQualifier.class);
    String receiver = JavaExpression.getImplicitReceiver(fieldElement).toString();
    String expression = receiver + "." + fieldElement.getSimpleName();
    builder.setValue("expression", new String[] {expression});
    builder.setValue("qualifier", AnnotationUtils.annotationMirrorToClass(qualifier));
    return builder.build();
  }

  /**
   * Add a new entry to the shared CFG. If this is a subchecker, this method delegates to the
   * superchecker's GenericAnnotatedTypeFactory, if it exists. Duplicate keys must map to the same
   * CFG.
   *
   * <p>Calls to this method should be guarded by checking {@link #hasOrIsSubchecker}; it is
   * nonsensical to have a shared CFG when a checker is running alone.
   *
   * @param tree the source code corresponding to cfg
   * @param cfg the control flow graph to use for tree
   * @return whether a shared CFG was found to actually add to (duplicate keys also return true)
   */
  public boolean addSharedCFGForTree(Tree tree, ControlFlowGraph cfg) {
    if (!shouldCache) {
      return false;
    }
    BaseTypeChecker parentChecker = this.checker.getUltimateParentChecker();
    @SuppressWarnings("interning") // Checking reference equality.
    boolean parentIsThisChecker = parentChecker == this.checker;
    if (parentIsThisChecker) {
      // This is the ultimate parent.
      if (this.subcheckerSharedCFG == null) {
        this.subcheckerSharedCFG = new HashMap<>(getCacheSize());
      }
      if (!this.subcheckerSharedCFG.containsKey(tree)) {
        this.subcheckerSharedCFG.put(tree, cfg);
      } else {
        assert this.subcheckerSharedCFG.get(tree).equals(cfg);
      }
      return true;
    }

    // This is a subchecker.
    if (parentChecker != null) {
      GenericAnnotatedTypeFactory<?, ?, ?, ?> parentAtf = parentChecker.getTypeFactory();
      return parentAtf.addSharedCFGForTree(tree, cfg);
    } else {
      return false;
    }
  }

  /**
   * Get the shared control flow graph used for {@code tree} by this checker's topmost superchecker.
   * Returns null if no information is available about the given tree, or if this checker has a
   * parent checker that does not have a GenericAnnotatedTypeFactory.
   *
   * <p>Calls to this method should be guarded by checking {@link #hasOrIsSubchecker}; it is
   * nonsensical to have a shared CFG when a checker is running alone.
   *
   * @param tree the tree whose CFG should be looked up
   * @return the CFG stored by this checker's uppermost superchecker for tree, or null if it is not
   *     available
   */
  public @Nullable ControlFlowGraph getSharedCFGForTree(Tree tree) {
    if (!shouldCache) {
      return null;
    }
    BaseTypeChecker parentChecker = this.checker.getUltimateParentChecker();
    @SuppressWarnings("interning") // Checking reference equality.
    boolean parentIsThisChecker = parentChecker == this.checker;
    if (parentIsThisChecker) {
      // This is the ultimate parent;
      return this.subcheckerSharedCFG == null
          ? null
          : this.subcheckerSharedCFG.getOrDefault(tree, null);
    }

    // This is a subchecker.
    if (parentChecker != null) {
      GenericAnnotatedTypeFactory<?, ?, ?, ?> parentAtf = parentChecker.getTypeFactory();
      return parentAtf.getSharedCFGForTree(tree);
    } else {
      return null;
    }
  }

  /**
   * If kind = CONDITIONALPOSTCONDITION, return the result element, e.g. {@link
   * EnsuresQualifierIf#result}. Otherwise, return null.
   *
   * @param kind the kind of {@code contractAnnotation}
   * @param contractAnnotation a {@link RequiresQualifier}, {@link EnsuresQualifier}, or {@link
   *     EnsuresQualifierIf}
   * @return the {@code result} element of {@code contractAnnotation}, or null if it doesn't have a
   *     {@code result} element
   */
  public Boolean getEnsuresQualifierIfResult(
      Contract.Kind kind, AnnotationMirror contractAnnotation) {
    if (kind == Contract.Kind.CONDITIONALPOSTCONDITION) {
      if (contractAnnotation instanceof EnsuresQualifierIf) {
        // It's the framework annotation @EnsuresQualifierIf
        return AnnotationUtils.getElementValueBoolean(
            contractAnnotation, ensuresQualifierIfResultElement, /*default is irrelevant*/ false);
      } else {
        // It's a checker-specific annotation such as @EnsuresMinLenIf
        @SuppressWarnings("deprecation") // concrete annotation class is not known
        Boolean result =
            AnnotationUtils.getElementValue(contractAnnotation, "result", Boolean.class, false);
        return result;
      }
    } else {
      return null;
    }
  }

  /**
   * If {@code contractAnnotation} is a framework annotation, return its {@code expression} element.
   * Otherwise, {@code contractAnnotation} is defined in a checker. If kind =
   * CONDITIONALPOSTCONDITION, return its {@code expression} element, else return its {@code value}
   * element.
   *
   * @param kind the kind of {@code contractAnnotation}
   * @param contractAnnotation a {@link RequiresQualifier}, {@link EnsuresQualifier}, or {@link
   *     EnsuresQualifierIf}
   * @return the {@code result} element of {@code contractAnnotation}, or null if it doesn't have a
   *     {@code result} element
   */
  public List<String> getContractExpressions(
      Contract.Kind kind, AnnotationMirror contractAnnotation) {
    // First, handle framework annotations.
    if (contractAnnotation instanceof RequiresQualifier) {
      return AnnotationUtils.getElementValueArray(
          contractAnnotation, requiresQualifierExpressionElement, String.class);
    } else if (contractAnnotation instanceof EnsuresQualifier) {
      return AnnotationUtils.getElementValueArray(
          contractAnnotation, ensuresQualifierExpressionElement, String.class);
    } else if (contractAnnotation instanceof EnsuresQualifierIf) {
      return AnnotationUtils.getElementValueArray(
          contractAnnotation, ensuresQualifierIfExpressionElement, String.class);
    }
    // `contractAnnotation` is defined in a checker.
    String elementName = kind == Contract.Kind.CONDITIONALPOSTCONDITION ? "expression" : "value";
    @SuppressWarnings("deprecation") // concrete annotation class is not known
    List<String> result =
        AnnotationUtils.getElementValueArray(contractAnnotation, elementName, String.class, true);
    return result;
  }
}
