package org.checkerframework.framework.stub;

import com.github.javaparser.ParseProblemException;
import com.github.javaparser.Position;
import com.github.javaparser.Problem;
import com.github.javaparser.ast.AccessSpecifier;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.PackageDeclaration;
import com.github.javaparser.ast.StubUnit;
import com.github.javaparser.ast.body.AnnotationDeclaration;
import com.github.javaparser.ast.body.BodyDeclaration;
import com.github.javaparser.ast.body.CallableDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.EnumConstantDeclaration;
import com.github.javaparser.ast.body.EnumDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.ReceiverParameter;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.expr.ArrayInitializerExpr;
import com.github.javaparser.ast.expr.BooleanLiteralExpr;
import com.github.javaparser.ast.expr.CharLiteralExpr;
import com.github.javaparser.ast.expr.ClassExpr;
import com.github.javaparser.ast.expr.DoubleLiteralExpr;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.FieldAccessExpr;
import com.github.javaparser.ast.expr.IntegerLiteralExpr;
import com.github.javaparser.ast.expr.LongLiteralExpr;
import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
import com.github.javaparser.ast.expr.MemberValuePair;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.NormalAnnotationExpr;
import com.github.javaparser.ast.expr.NullLiteralExpr;
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.expr.UnaryExpr;
import com.github.javaparser.ast.nodeTypes.NodeWithRange;
import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithAccessModifiers;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.type.PrimitiveType;
import com.github.javaparser.ast.type.ReferenceType;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.type.TypeParameter;
import com.github.javaparser.ast.type.WildcardType;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.VariableTree;
import java.io.File;
import java.io.InputStream;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
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.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import org.checkerframework.checker.formatter.qual.FormatMethod;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.CanonicalName;
import org.checkerframework.checker.signature.qual.DotSeparatedIdentifiers;
import org.checkerframework.checker.signature.qual.FullyQualifiedName;
import org.checkerframework.framework.ajava.DefaultJointVisitor;
import org.checkerframework.framework.qual.AnnotatedFor;
import org.checkerframework.framework.qual.FromStubFile;
import org.checkerframework.framework.stub.AnnotationFileUtil.AnnotationFileType;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.util.JavaParserUtil;
import org.checkerframework.framework.util.element.ElementAnnotationUtil.ErrorTypeKindException;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TreeUtils;

// From an implementation perspective, this class represents a single annotation file (stub file or
// ajava file), notably its annotated types and its declaration annotations.
// From a client perspective, it has static methods as described below in the Javadoc.
/**
 * This class has three static methods. Each method parses an annotation file and adds annotations
 * to the {@link AnnotationFileAnnotations} passed as an argument.
 *
 * <p>The first main entry point is {@link #parseStubFile(String, InputStream, AnnotatedTypeFactory,
 * ProcessingEnvironment, AnnotationFileAnnotations, AnnotationFileUtil.AnnotationFileType)}, which
 * side-effects its last argument. It operates in two steps. First, it calls the Annotation File
 * Parser to parse an annotation file. Then, it walks the AST to create/collect types and
 * declaration annotations.
 *
 * <p>The second main entry point is {@link #parseAjavaFile(String, InputStream,
 * CompilationUnitTree, AnnotatedTypeFactory, ProcessingEnvironment, AnnotationFileAnnotations)}.
 * This behaves the same as {@link AnnotationFileParser#parseStubFile(String, InputStream,
 * AnnotatedTypeFactory, ProcessingEnvironment, AnnotationFileAnnotations,
 * AnnotationFileUtil.AnnotationFileType)}, but takes an ajava file instead.
 *
 * <p>The other entry point is {@link #parseJdkFileAsStub}.
 */
public class AnnotationFileParser {

  /**
   * The type of file being parsed: stub file or ajava file. Also indicates its source, such as from
   * the JDK, built in, or from the command line.
   *
   * <p>Non-JDK stub files override JDK stub files. (Ordinarily, if two stubs are provided, they are
   * merged.)
   *
   * <p>For a built-in stub file,
   *
   * <ul>
   *   <li>private declarations are ignored,
   *   <li>some warning messages are not issued, and
   * </ul>
   */
  private final AnnotationFileType fileType;

  /**
   * If parsing an ajava file, represents the javac tree for the compilation root of the file being
   * parsed.
   */
  private CompilationUnitTree root;

  /**
   * Whether to print warnings about types/members that were not found. The warning states that a
   * class/field in the file is not found on the user's real classpath. Since the file may contain
   * packages that are not on the classpath, this can be OK, so default to false.
   */
  private final boolean warnIfNotFound;

  /**
   * Whether to ignore missing classes even when warnIfNotFound is set to true. This allows the
   * files to contain classes not in the classpath (even if another class in the classpath has the
   * same package), but still warn if members of the class (methods, fields) are missing. This
   * option does nothing unless warnIfNotFound is also set.
   */
  private final boolean warnIfNotFoundIgnoresClasses;

  /** Whether to print warnings about stub files that overwrite annotations from bytecode. */
  private final boolean warnIfStubOverwritesBytecode;

  /**
   * Whether to print warnings about stub files that are redundant with annotations from bytecode.
   */
  private final boolean warnIfStubRedundantWithBytecode;

  /** The diagnostic kind for stub file warnings: NOTE or WARNING. */
  private final Diagnostic.Kind stubWarnDiagnosticKind;

  /** Whether to print verbose debugging messages. */
  private final boolean debugAnnotationFileParser;

  /** The name of the file being processed; used only for diagnostic messages. */
  private final String filename;

  /**
   * The AST of the parsed file that this class is processing. May be null if there was a problem
   * parsing the file. (TODO: Should the Checker Framework just halt in that case?)
   */
  // Not final in order to accommodate a default value.
  private StubUnit stubUnit;

  private final ProcessingEnvironment processingEnv;
  private final AnnotatedTypeFactory atypeFactory;
  private final Elements elements;

  /**
   * The set of annotations found in the file. Keys are both fully-qualified and simple names. There
   * are two entries for each annotation: the annotation's simple name and its fully-qualified name.
   *
   * <p>The map is populated from import statements and also by {@link #getAnnotation(
   * AnnotationExpr, Map)} for annotations that are used fully-qualified.
   *
   * @see #getImportedAnnotations
   */
  private Map<String, TypeElement> allAnnotations;

  /**
   * A list of the fully-qualified names of enum constants and static fields with constant values
   * that have been imported.
   */
  private final List<@FullyQualifiedName String> importedConstants = new ArrayList<>();

  /** A map of imported fully-qualified type names to type elements. */
  private final Map<String, TypeElement> importedTypes = new HashMap<>();

  /** The annotation {@code @FromStubFile}. */
  private final AnnotationMirror fromStubFileAnno;

  /**
   * List of AnnotatedTypeMirrors for class or method type parameters that are in scope of the
   * elements currently parsed.
   */
  private final List<AnnotatedTypeVariable> typeParameters = new ArrayList<>();

  /**
   * The annotations on the declared package of the complation unit being processed. Contains null
   * if not processing a compilation unit or if the file has no declared package.
   */
  @Nullable List<AnnotationExpr> packageAnnos;

  // The following variables are stored in the AnnotationFileParser because otherwise they would
  // need to be passed through everywhere, which would be verbose.

  /**
   * The name of the type that is currently being parsed. After processing a package declaration but
   * before processing a type declaration, the type part of this may be null.
   *
   * <p>It is used both for resolving symbols and for error messages.
   */
  private FqName typeBeingParsed;

  /**
   * Contains the annotations of the file currently being processed, or null if not currently
   * processing a file. The {@code process*} methods side-effect this data structure.
   */
  @Nullable AnnotationFileAnnotations annotationFileAnnos;

  /** The line separator. */
  private static final String LINE_SEPARATOR = System.lineSeparator().intern();

  /** Whether or not the {@code -AmergeStubsWithSource} command-line argument was passed. */
  private final boolean mergeStubsWithSource;

  /**
   * The result of calling AnnotationFileParser.parse: the annotated types and declaration
   * annotations from the file.
   */
  public static class AnnotationFileAnnotations {

    /**
     * Map from element to its type as declared in the annotation file.
     *
     * <p>This is a fine-grained mapping that contains all sorts of elements; contrast with {@link
     * #fakeOverrides}.
     */
    public final Map<Element, AnnotatedTypeMirror> atypes = new HashMap<>();

    /**
     * Map from a name (actually declaration element string) to the set of declaration annotations
     * on it, as written in the annotation file.
     *
     * <p>Map keys cannot be Element, because a different Element appears in the annotation files
     * than in the real files. So, map keys are the verbose element name, as returned by
     * ElementUtils.getQualifiedName.
     */
    public final Map<String, Set<AnnotationMirror>> declAnnos = new HashMap<>(1);

    /**
     * Map from a method element to all the fake overrides of it. Given a key {@code ee}, the fake
     * overrides are always in subtypes of {@code ee.getEnclosingElement()}, which is the same as
     * {@code ee.getReceiverType()}.
     */
    public final Map<ExecutableElement, List<Pair<TypeMirror, AnnotatedTypeMirror>>> fakeOverrides =
        new HashMap<>(1);
  }

  /**
   * Create a new AnnotationFileParser object, which will parse and extract annotations from the
   * given file.
   *
   * @param filename name of annotation file, used only for diagnostic messages
   * @param atypeFactory AnnotatedTypeFactory to use
   * @param processingEnv ProcessingEnvironment to use
   * @param fileType the type of file being parsed (stub file or ajava file) and its source
   */
  private AnnotationFileParser(
      String filename,
      AnnotatedTypeFactory atypeFactory,
      ProcessingEnvironment processingEnv,
      AnnotationFileType fileType) {
    this.filename = filename;
    this.atypeFactory = atypeFactory;
    this.processingEnv = processingEnv;
    this.elements = processingEnv.getElementUtils();
    this.fileType = fileType;
    this.root = null;

    // TODO: This should use SourceChecker.getOptions() to allow
    // setting these flags per checker.
    Map<String, String> options = processingEnv.getOptions();
    this.warnIfNotFound = fileType.isCommandLine() || options.containsKey("stubWarnIfNotFound");
    this.warnIfNotFoundIgnoresClasses = options.containsKey("stubWarnIfNotFoundIgnoresClasses");
    this.warnIfStubOverwritesBytecode = options.containsKey("stubWarnIfOverwritesBytecode");
    this.warnIfStubRedundantWithBytecode =
        options.containsKey("stubWarnIfRedundantWithBytecode")
            && atypeFactory.shouldWarnIfStubRedundantWithBytecode();
    this.stubWarnDiagnosticKind =
        options.containsKey("stubWarnNote") ? Diagnostic.Kind.NOTE : Diagnostic.Kind.WARNING;
    this.debugAnnotationFileParser = options.containsKey("stubDebug");

    this.fromStubFileAnno = AnnotationBuilder.fromClass(elements, FromStubFile.class);

    this.mergeStubsWithSource = atypeFactory.getChecker().hasOption("mergeStubsWithSource");
  }

  /**
   * Sets the root of the file currently being parsed to {@code root}.
   *
   * @param root compilation unit for the file being parsed
   */
  private void setRoot(CompilationUnitTree root) {
    this.root = root;
  }

  /**
   * All annotations defined in the package (but not those nested within classes in the package).
   * Keys are both fully-qualified and simple names.
   *
   * @param packageElement a package
   * @return a map from annotation name to TypeElement
   */
  public static Map<String, TypeElement> annosInPackage(PackageElement packageElement) {
    return createNameToAnnotationMap(ElementFilter.typesIn(packageElement.getEnclosedElements()));
  }

  /**
   * All annotations declared (directly) within a class. Keys are both fully-qualified and simple
   * names.
   *
   * @param typeElement a type
   * @return a map from annotation name to TypeElement
   */
  public static Map<String, TypeElement> annosInType(TypeElement typeElement) {
    return createNameToAnnotationMap(ElementFilter.typesIn(typeElement.getEnclosedElements()));
  }

  /**
   * All annotations declared within any of the given elements.
   *
   * @param typeElements the elements whose annotations to retrieve
   * @return a map from annotation names (both fully-qualified and simple names) to TypeElement
   */
  public static Map<String, TypeElement> createNameToAnnotationMap(List<TypeElement> typeElements) {
    Map<String, TypeElement> result = new HashMap<>();
    for (TypeElement typeElm : typeElements) {
      if (typeElm.getKind() == ElementKind.ANNOTATION_TYPE) {
        putIfAbsent(result, typeElm.getSimpleName().toString(), typeElm);
        putIfAbsent(result, typeElm.getQualifiedName().toString(), typeElm);
      }
    }
    return result;
  }

  /**
   * Get all members of a Type that are importable in an annotation file. Currently these are values
   * of enums, or compile time constants.
   *
   * @param typeElement the type whose members to return
   * @return a list of fully-qualified member names
   */
  private static List<@FullyQualifiedName String> getImportableMembers(TypeElement typeElement) {
    List<VariableElement> memberElements =
        ElementFilter.fieldsIn(typeElement.getEnclosedElements());
    List<@FullyQualifiedName String> result = new ArrayList<>();
    for (VariableElement varElement : memberElements) {
      if (varElement.getConstantValue() != null
          || varElement.getKind() == ElementKind.ENUM_CONSTANT) {
        @SuppressWarnings("signature") // string concatenation
        @FullyQualifiedName String fqName =
            typeElement.getQualifiedName().toString() + "." + varElement.getSimpleName().toString();
        result.add(fqName);
      }
    }
    return result;
  }

  /**
   * Returns all annotations imported by the annotation file, as a value for {@link
   * #allAnnotations}. Note that this also modifies {@link #importedConstants} and {@link
   * #importedTypes}.
   *
   * <p>This method misses annotations that are not imported. The {@link #getAnnotation} method
   * compensates for this deficiency by adding any fully-qualified annotation that it encounters.
   *
   * @return a map from names to TypeElement, for all annotations imported by the annotation file.
   *     Two entries for each annotation: one for the simple name and another for the
   *     fully-qualified name, with the same value.
   * @see #allAnnotations
   */
  private Map<String, TypeElement> getImportedAnnotations() {
    Map<String, TypeElement> result = new HashMap<>();

    // TODO: The size can be greater than 1, but this ignores all but the first element.
    assert !stubUnit.getCompilationUnits().isEmpty();
    CompilationUnit cu = stubUnit.getCompilationUnits().get(0);

    if (cu.getImports() == null) {
      return result;
    }

    for (ImportDeclaration importDecl : cu.getImports()) {
      try {
        if (importDecl.isAsterisk()) {
          @SuppressWarnings("signature" // https://tinyurl.com/cfissue/3094:
          // com.github.javaparser.ast.expr.Name inherits toString,
          // so there can be no annotation for it
          )
          @DotSeparatedIdentifiers String imported = importDecl.getName().toString();
          if (importDecl.isStatic()) {
            // Wildcard import of members of a type (class or interface)
            TypeElement element = getTypeElement(imported, "Imported type not found", importDecl);
            if (element != null) {
              // Find nested annotations
              // Find compile time constant fields, or values of an enum
              putAllNew(result, annosInType(element));
              importedConstants.addAll(getImportableMembers(element));
              addEnclosingTypesToImportedTypes(element);
            }

          } else {
            // Wildcard import of members of a package
            PackageElement element = findPackage(imported, importDecl);
            if (element != null) {
              putAllNew(result, annosInPackage(element));
              addEnclosingTypesToImportedTypes(element);
            }
          }
        } else {
          // A single (non-wildcard) import.
          @SuppressWarnings("signature" // importDecl is non-wildcard, so its name is
          // @FullyQualifiedName
          )
          @FullyQualifiedName String imported = importDecl.getNameAsString();

          final TypeElement importType = elements.getTypeElement(imported);
          if (importType == null && !importDecl.isStatic()) {
            // Class or nested class (according to JSL), but we can't resolve

            stubWarnNotFound(importDecl, "Imported type not found: " + imported);
          } else if (importType == null) {
            // static import of field or method.

            Pair<@FullyQualifiedName String, String> typeParts =
                AnnotationFileUtil.partitionQualifiedName(imported);
            String type = typeParts.first;
            String fieldName = typeParts.second;
            TypeElement enclType =
                getTypeElement(
                    type,
                    String.format("Enclosing type of static field %s not found", fieldName),
                    importDecl);

            if (enclType != null) {
              // Don't use findFieldElement(enclType, fieldName), because we don't
              // want a warning, imported might be a method.
              for (VariableElement field : ElementUtils.getAllFieldsIn(enclType, elements)) {
                // field.getSimpleName() is a CharSequence, not a String
                if (fieldName.equals(field.getSimpleName().toString())) {
                  importedConstants.add(imported);
                }
              }
            }

          } else if (importType.getKind() == ElementKind.ANNOTATION_TYPE) {
            // Single annotation or nested annotation
            TypeElement annoElt = elements.getTypeElement(imported);
            if (annoElt != null) {
              putIfAbsent(result, annoElt.getSimpleName().toString(), annoElt);
              importedTypes.put(annoElt.getSimpleName().toString(), annoElt);
            } else {
              stubWarnNotFound(importDecl, "Could not load import: " + imported);
            }
          } else {
            // Class or nested class
            // TODO: Is this needed?
            importedConstants.add(imported);
            TypeElement element = getTypeElement(imported, "Imported type not found", importDecl);
            importedTypes.put(element.getSimpleName().toString(), element);
          }
        }
      } catch (AssertionError error) {
        stubWarnNotFound(importDecl, error.toString());
      }
    }
    return result;
  }

  // If a member is imported, then consider every containing class to also be imported.
  private void addEnclosingTypesToImportedTypes(Element element) {
    for (Element enclosedEle : element.getEnclosedElements()) {
      if (enclosedEle.getKind().isClass()) {
        importedTypes.put(enclosedEle.getSimpleName().toString(), (TypeElement) enclosedEle);
      }
    }
  }

  /**
   * The main entry point. Parse a stub file and side-effects the {@code annotationFileAnnos}
   * argument.
   *
   * @param filename name of stub file, used only for diagnostic messages
   * @param inputStream of stub file to parse
   * @param atypeFactory AnnotatedTypeFactory to use
   * @param processingEnv ProcessingEnvironment to use
   * @param annotationFileAnnos annotations from the annotation file; side-effected by this method
   * @param fileType the annotation file type and source
   */
  public static void parseStubFile(
      String filename,
      InputStream inputStream,
      AnnotatedTypeFactory atypeFactory,
      ProcessingEnvironment processingEnv,
      AnnotationFileAnnotations annotationFileAnnos,
      AnnotationFileType fileType) {
    AnnotationFileParser afp =
        new AnnotationFileParser(filename, atypeFactory, processingEnv, fileType);
    try {
      afp.parseStubUnit(inputStream);
      afp.process(annotationFileAnnos);
    } catch (ParseProblemException e) {
      for (Problem p : e.getProblems()) {
        afp.warn(null, p.getVerboseMessage());
      }
    }
  }

  /**
   * The main entry point when parsing an ajava file. Parses an ajava file and side-effects the last
   * two arguments.
   *
   * @param filename name of ajava file, used only for diagnostic messages
   * @param inputStream of ajava file to parse
   * @param root javac tree for the file to be parsed
   * @param atypeFactory AnnotatedTypeFactory to use
   * @param processingEnv ProcessingEnvironment to use
   * @param ajavaAnnos annotations from the ajava file; side-effected by this method
   */
  public static void parseAjavaFile(
      String filename,
      InputStream inputStream,
      CompilationUnitTree root,
      AnnotatedTypeFactory atypeFactory,
      ProcessingEnvironment processingEnv,
      AnnotationFileAnnotations ajavaAnnos) {
    AnnotationFileParser afp =
        new AnnotationFileParser(filename, atypeFactory, processingEnv, AnnotationFileType.AJAVA);
    try {
      afp.parseStubUnit(inputStream);
      JavaParserUtil.concatenateAddedStringLiterals(afp.stubUnit);
      afp.setRoot(root);
      afp.process(ajavaAnnos);
    } catch (ParseProblemException e) {
      for (Problem p : e.getProblems()) {
        afp.warn(null, p.getVerboseMessage());
      }
    }
  }

  /**
   * Parse a stub file that is a part of the annotated JDK and side-effects the {@code stubAnnos}
   * argument.
   *
   * @param filename name of stub file, used only for diagnostic messages
   * @param inputStream of stub file to parse
   * @param atypeFactory AnnotatedTypeFactory to use
   * @param processingEnv ProcessingEnvironment to use
   * @param stubAnnos annotations from the stub file; side-effected by this method
   */
  public static void parseJdkFileAsStub(
      String filename,
      InputStream inputStream,
      AnnotatedTypeFactory atypeFactory,
      ProcessingEnvironment processingEnv,
      AnnotationFileAnnotations stubAnnos) {
    parseStubFile(
        filename, inputStream, atypeFactory, processingEnv, stubAnnos, AnnotationFileType.JDK_STUB);
  }

  /**
   * Delegate to the Stub Parser to parse the annotation file to an AST, and save it in {@link
   * #stubUnit}. Also sets {@link #allAnnotations}. Does not copy annotations out of {@link
   * #stubUnit}; that is done by the {@code process*} methods.
   *
   * <p>Subsequently, all work uses the AST.
   *
   * @param inputStream the stream from which to read an annotation file
   */
  private void parseStubUnit(InputStream inputStream) {
    if (debugAnnotationFileParser) {
      stubDebug(String.format("parsing annotation file %s", filename));
    }
    stubUnit = JavaParserUtil.parseStubUnit(inputStream);

    // getImportedAnnotations() also modifies importedConstants and importedTypes. This should
    // be refactored to be nicer.
    allAnnotations = getImportedAnnotations();
    if (allAnnotations.isEmpty()
        && fileType.isStub()
        && fileType != AnnotationFileType.AJAVA_AS_STUB) {
      // Issue a warning if the stub file contains no import statements.  The warning is
      // incorrect if the stub file contains fully-qualified annotations.
      stubWarnNotFound(
          null,
          String.format(
              "No supported annotations found! Does stub file %s import them?", filename));
    }
    // Annotations in java.lang might be used without an import statement, so add them in case.
    allAnnotations.putAll(annosInPackage(findPackage("java.lang", null)));
  }

  /**
   * Process {@link #stubUnit}, which is the AST produced by {@link #parseStubUnit}. Processing
   * means copying annotations from Stub Parser data structures to {@code #annotationFileAnnos}.
   *
   * @param annotationFileAnnos annotations from the file; side-effected by this method
   */
  private void process(AnnotationFileAnnotations annotationFileAnnos) {
    this.annotationFileAnnos = annotationFileAnnos;
    processStubUnit(this.stubUnit);
    this.annotationFileAnnos = null;
  }

  /**
   * Process the given StubUnit: copy its annotations to {@code #annotationFileAnnos}.
   *
   * @param su the StubUnit to process
   */
  private void processStubUnit(StubUnit su) {
    for (CompilationUnit cu : su.getCompilationUnits()) {
      processCompilationUnit(cu);
    }
  }

  /**
   * Process the given CompilationUnit: copy its annotations to {@code #annotationFileAnnos}.
   *
   * @param cu the CompilationUnit to process
   */
  private void processCompilationUnit(CompilationUnit cu) {

    if (!cu.getPackageDeclaration().isPresent()) {
      packageAnnos = null;
      typeBeingParsed = new FqName(null, null);
    } else {
      PackageDeclaration pDecl = cu.getPackageDeclaration().get();
      packageAnnos = pDecl.getAnnotations();
      processPackage(pDecl);
    }

    if (fileType.isStub()) {
      if (cu.getTypes() != null) {
        for (TypeDeclaration<?> typeDeclaration : cu.getTypes()) {
          // Not processing an ajava file, so ignore the return value.
          processTypeDecl(typeDeclaration, null, null);
        }
      }
    } else {
      root.accept(new AjavaAnnotationCollectorVisitor(), cu);
    }

    packageAnnos = null;
  }

  /**
   * Process the given package declaration: copy its annotations to {@code #annotationFileAnnos}.
   *
   * @param packDecl the package declaration to process
   */
  private void processPackage(PackageDeclaration packDecl) {
    assert (packDecl != null);
    if (!isAnnotatedForThisChecker(packDecl.getAnnotations())) {
      return;
    }
    String packageName = packDecl.getNameAsString();
    typeBeingParsed = new FqName(packageName, null);
    Element elem = elements.getPackageElement(packageName);
    // If the element lookup fails (that is, elem == null), it's because we have an annotation for a
    // package that isn't on the classpath, which is fine.
    if (elem != null) {
      recordDeclAnnotation(elem, packDecl.getAnnotations(), packDecl);
    }
    // TODO: Handle atypes???
  }

  /**
   * Returns true if the given program construct need not be read: it is private and one of the
   * following is true:
   *
   * <ul>
   *   <li>It is in the annotated JDK. Private constructs can't be referenced outside of the JDK and
   *       might refer to types that are not accessible.
   *   <li>It is not an ajava file and {@code -AmergeStubsWithSource} was not supplied. As described
   *       at https://checkerframework.org/manual/#stub-multiple-specifications, source files take
   *       precedence over stub files unless {@code -AmergeStubsWithSource} is supplied. As
   *       described at https://checkerframework.org/manual/#ajava-using, source files do not take
   *       precedence over ajava files (when reading an ajava file, it is as if {@code
   *       -AmergeStubsWithSource} were supplied).
   * </ul>
   *
   * @param node a declaration
   * @return true if the given program construct is in the annotated JDK and is private
   */
  private boolean skipNode(NodeWithAccessModifiers<?> node) {
    // Must include everything with no access modifier, because stub files are allowed to omit the
    // access modifier.  Also, interface methods have no access modifier, but they are still public.
    // Must include protected JDK methods.  For example, Object.clone is protected, but it contains
    // annotations that apply to calls like `super.clone()` and `myArray.clone()`.
    return (fileType == AnnotationFileType.BUILTIN_STUB
            || (fileType.isStub() && !mergeStubsWithSource))
        && node.getModifiers().contains(Modifier.privateModifier());
  }

  /**
   * Process a type declaration: copy its annotations to {@code #annotationFileAnnos}.
   *
   * <p>This method stores the declaration's type parameters in {@link #typeParameters}. When
   * processing an ajava file, where traversal is handled externaly by a {@link
   * org.checkerframework.framework.ajava.JointJavacJavaParserVisitor}, these type variables must be
   * removed after processing the type's members. Otherwise, this method removes them.
   *
   * @param typeDecl the type declaration to process
   * @param outertypeName the name of the containing class, when processing a nested class;
   *     otherwise null
   * @param classTree the tree corresponding to typeDecl if processing an ajava file, null otherwise
   * @return a list of types variables for {@code typeDecl}. Only non-null if processing an ajava
   *     file, in which case the contents should be removed from {@link #typeParameters} after
   *     processing the type declaration's members
   */
  private List<AnnotatedTypeVariable> processTypeDecl(
      TypeDeclaration<?> typeDecl, String outertypeName, @Nullable ClassTree classTree) {
    assert typeBeingParsed != null;
    if (skipNode(typeDecl)) {
      return null;
    }
    String innerName;
    @FullyQualifiedName String fqTypeName;
    TypeElement typeElt;
    if (classTree != null) {
      typeElt = TreeUtils.elementFromDeclaration(classTree);
      innerName = typeElt.getQualifiedName().toString();
      typeBeingParsed = new FqName(typeBeingParsed.packageName, innerName);
      fqTypeName = typeBeingParsed.toString();
    } else {
      String packagePrefix = outertypeName == null ? "" : outertypeName + ".";
      innerName = packagePrefix + typeDecl.getNameAsString();
      typeBeingParsed = new FqName(typeBeingParsed.packageName, innerName);
      fqTypeName = typeBeingParsed.toString();
      typeElt = elements.getTypeElement(fqTypeName);
    }

    if (!isAnnotatedForThisChecker(typeDecl.getAnnotations())) {
      return null;
    }
    if (typeElt == null) {
      if (debugAnnotationFileParser
          || (!warnIfNotFoundIgnoresClasses
              && !hasNoAnnotationFileParserWarning(typeDecl.getAnnotations())
              && !hasNoAnnotationFileParserWarning(packageAnnos))) {
        if (elements.getAllTypeElements(fqTypeName).isEmpty()) {
          stubWarnNotFound(typeDecl, "Type not found: " + fqTypeName);
        } else {
          stubWarnNotFound(
              typeDecl,
              "Type not found uniquely: "
                  + fqTypeName
                  + " : "
                  + elements.getAllTypeElements(fqTypeName));
        }
      }
      return null;
    }

    List<AnnotatedTypeVariable> typeDeclTypeParameters = null;
    if (typeElt.getKind() == ElementKind.ENUM) {
      if (!(typeDecl instanceof EnumDeclaration)) {
        warn(
            typeDecl,
            innerName
                + " is an enum, but stub file declared it as "
                + typeDecl.toString().split("\\R", 2)[0]
                + "...");
        return null;
      }
      typeDeclTypeParameters = processEnum((EnumDeclaration) typeDecl, typeElt);
      typeParameters.addAll(typeDeclTypeParameters);
    } else if (typeElt.getKind() == ElementKind.ANNOTATION_TYPE) {
      if (!(typeDecl instanceof AnnotationDeclaration)) {
        warn(
            typeDecl,
            innerName
                + " is an annotation, but stub file declared it as "
                + typeDecl.toString().split("\\R", 2)[0]
                + "...");
        return null;
      }
      stubWarnNotFound(typeDecl, "Skipping annotation type: " + fqTypeName);
    } else if (typeDecl instanceof ClassOrInterfaceDeclaration) {
      if (!(typeDecl instanceof ClassOrInterfaceDeclaration)) {
        warn(
            typeDecl,
            innerName
                + " is a class or interface, but stub file declared it as "
                + typeDecl.toString().split("\\R", 2)[0]
                + "...");
        return null;
      }
      typeDeclTypeParameters = processType((ClassOrInterfaceDeclaration) typeDecl, typeElt);
      typeParameters.addAll(typeDeclTypeParameters);
    } // else it's an EmptyTypeDeclaration.  TODO:  An EmptyTypeDeclaration can have
    // annotations, right?

    // If processing an ajava file, then traversal is handled by a visitor, rather than the rest
    // of this method.
    if (fileType == AnnotationFileType.AJAVA) {
      return typeDeclTypeParameters;
    }

    Pair<Map<Element, BodyDeclaration<?>>, Map<Element, List<BodyDeclaration<?>>>> members =
        getMembers(typeDecl, typeElt, typeDecl);
    for (Map.Entry<Element, BodyDeclaration<?>> entry : members.first.entrySet()) {
      final Element elt = entry.getKey();
      final BodyDeclaration<?> decl = entry.getValue();
      switch (elt.getKind()) {
        case FIELD:
          processField((FieldDeclaration) decl, (VariableElement) elt);
          break;
        case ENUM_CONSTANT:
          processEnumConstant((EnumConstantDeclaration) decl, (VariableElement) elt);
          break;
        case CONSTRUCTOR:
        case METHOD:
          processCallableDeclaration((CallableDeclaration<?>) decl, (ExecutableElement) elt);
          break;
        case CLASS:
        case INTERFACE:
          // Not processing an ajava file, so ignore the return value.
          processTypeDecl((ClassOrInterfaceDeclaration) decl, innerName, null);
          break;
        case ENUM:
          // Not processing an ajava file, so ignore the return value.
          processTypeDecl((EnumDeclaration) decl, innerName, null);
          break;
        default:
          /* do nothing */
          stubWarnNotFound(decl, "AnnotationFileParser ignoring: " + elt);
          break;
      }
    }
    for (Map.Entry<Element, List<BodyDeclaration<?>>> entry : members.second.entrySet()) {
      ExecutableElement fakeOverridden = (ExecutableElement) entry.getKey();
      List<BodyDeclaration<?>> fakeOverrideDecls = entry.getValue();
      for (BodyDeclaration<?> bodyDecl : fakeOverrideDecls) {
        processFakeOverride(fakeOverridden, (CallableDeclaration<?>) bodyDecl, typeElt);
      }
    }

    if (typeDeclTypeParameters != null) {
      typeParameters.removeAll(typeDeclTypeParameters);
    }

    return null;
  }

  /**
   * Returns true if the argument contains {@code @NoAnnotationFileParserWarning}.
   *
   * @param aexprs collection of annotation expressions
   * @return true if {@code aexprs} contains {@code @NoAnnotationFileParserWarning}
   */
  private boolean hasNoAnnotationFileParserWarning(Iterable<AnnotationExpr> aexprs) {
    if (aexprs == null) {
      return false;
    }
    for (AnnotationExpr anno : aexprs) {
      if (anno.getNameAsString().equals("NoAnnotationFileParserWarning")) {
        return true;
      }
    }
    return false;
  }

  /**
   * Process the type's declaration: copy its annotations to {@code #annotationFileAnnos}. Does not
   * process any of its members. Returns the type's type parameter declarations.
   *
   * @param decl a type declaration
   * @param elt the type's element
   * @return the type's type parameter declarations
   */
  private List<AnnotatedTypeVariable> processType(
      ClassOrInterfaceDeclaration decl, TypeElement elt) {

    recordDeclAnnotation(elt, decl.getAnnotations(), decl);
    AnnotatedDeclaredType type = atypeFactory.fromElement(elt);
    annotate(type, decl.getAnnotations(), decl);

    final List<? extends AnnotatedTypeMirror> typeArguments = type.getTypeArguments();
    final List<TypeParameter> typeParameters = decl.getTypeParameters();

    // It can be the case that args=[] and params=null, so don't crash in that case.
    // if ((typeParameters == null) != (typeArguments == null)) {
    //     throw new Error(String.format("parseType (%s, %s): inconsistent nullness for args and
    // params%n  args = %s%n  params = %s%n", decl, elt, typeArguments, typeParameters));
    // }

    if (debugAnnotationFileParser) {
      int numParams = (typeParameters == null ? 0 : typeParameters.size());
      int numArgs = (typeArguments == null ? 0 : typeArguments.size());
      if (numParams != numArgs) {
        stubDebug(
            String.format(
                "parseType:  mismatched sizes for typeParameters=%s (size %d) and typeArguments=%s"
                    + " (size %d); decl=%s; elt=%s (%s); type=%s (%s); typeBeingParsed=%s",
                typeParameters,
                numParams,
                typeArguments,
                numArgs,
                decl.toString().replace(LINE_SEPARATOR, " "),
                elt.toString().replace(LINE_SEPARATOR, " "),
                elt.getClass(),
                type,
                type.getClass(),
                typeBeingParsed));
        stubDebug("Proceeding despite mismatched sizes");
      }
    }

    annotateTypeParameters(decl, elt, typeArguments, typeParameters);
    annotateSupertypes(decl, type);
    putMerge(annotationFileAnnos.atypes, elt, type);
    List<AnnotatedTypeVariable> typeVariables = new ArrayList<>(type.getTypeArguments().size());
    for (AnnotatedTypeMirror typeV : type.getTypeArguments()) {
      if (typeV.getKind() != TypeKind.TYPEVAR) {
        warn(
            decl,
            "expected an AnnotatedTypeVariable but found type kind "
                + typeV.getKind()
                + ": "
                + typeV);
      } else {
        typeVariables.add((AnnotatedTypeVariable) typeV);
      }
    }
    return typeVariables;
  }

  /**
   * Process an enum: copy its annotations to {@code #annotationFileAnnos}. Returns the enum's type
   * parameter declarations.
   *
   * @param decl enum declaration
   * @param elt element representing enum
   * @return the enum's type parameter declarations
   */
  private List<AnnotatedTypeVariable> processEnum(EnumDeclaration decl, TypeElement elt) {

    recordDeclAnnotation(elt, decl.getAnnotations(), decl);
    AnnotatedDeclaredType type = atypeFactory.fromElement(elt);
    annotate(type, decl.getAnnotations(), decl);

    putMerge(annotationFileAnnos.atypes, elt, type);
    List<AnnotatedTypeVariable> typeVariables = new ArrayList<>(type.getTypeArguments().size());
    for (AnnotatedTypeMirror typeV : type.getTypeArguments()) {
      if (typeV.getKind() != TypeKind.TYPEVAR) {
        warn(
            decl,
            "expected an AnnotatedTypeVariable but found type kind "
                + typeV.getKind()
                + ": "
                + typeV);
      } else {
        typeVariables.add((AnnotatedTypeVariable) typeV);
      }
    }
    return typeVariables;
  }

  private void annotateSupertypes(
      ClassOrInterfaceDeclaration typeDecl, AnnotatedDeclaredType type) {
    if (typeDecl.getExtendedTypes() != null) {
      for (ClassOrInterfaceType supertype : typeDecl.getExtendedTypes()) {
        AnnotatedDeclaredType annotatedSupertype =
            findAnnotatedType(supertype, type.directSupertypes(), typeDecl);
        if (annotatedSupertype == null) {
          warn(
              typeDecl,
              "stub file does not match bytecode: "
                  + "could not find superclass "
                  + supertype
                  + " from type "
                  + type);
        } else {
          annotate(annotatedSupertype, supertype, null, typeDecl);
        }
      }
    }
    if (typeDecl.getImplementedTypes() != null) {
      for (ClassOrInterfaceType supertype : typeDecl.getImplementedTypes()) {
        AnnotatedDeclaredType annotatedSupertype =
            findAnnotatedType(supertype, type.directSupertypes(), typeDecl);
        if (annotatedSupertype == null) {
          warn(
              typeDecl,
              "stub file does not match bytecode: "
                  + "could not find superinterface "
                  + supertype
                  + " from type "
                  + type);
        } else {
          annotate(annotatedSupertype, supertype, null, typeDecl);
        }
      }
    }
  }

  /**
   * Process a method or constructor declaration: copy its annotations to {@code
   * #annotationFileAnnos}.
   *
   * @param decl a method or constructor declaration, as read from an annotation file
   * @param elt the method or constructor's element
   * @return type variables for the method
   */
  private List<AnnotatedTypeVariable> processCallableDeclaration(
      CallableDeclaration<?> decl, ExecutableElement elt) {
    if (!isAnnotatedForThisChecker(decl.getAnnotations())) {
      return null;
    }
    // Declaration annotations
    recordDeclAnnotation(elt, decl.getAnnotations(), decl);
    if (decl.isMethodDeclaration()) {
      // AnnotationFileParser parses all annotations in type annotation position as type
      // annotations.
      recordDeclAnnotation(elt, ((MethodDeclaration) decl).getType().getAnnotations(), decl);
    }
    markAsFromStubFile(elt);

    AnnotatedExecutableType methodType = atypeFactory.fromElement(elt);
    AnnotatedExecutableType origMethodType =
        warnIfStubRedundantWithBytecode ? methodType.deepCopy() : null;

    // Type Parameters
    annotateTypeParameters(decl, elt, methodType.getTypeVariables(), decl.getTypeParameters());
    typeParameters.addAll(methodType.getTypeVariables());

    // Return type, from declaration annotations on the method or constructor
    if (decl.isMethodDeclaration()) {
      try {
        annotate(
            methodType.getReturnType(),
            ((MethodDeclaration) decl).getType(),
            decl.getAnnotations(),
            decl);
      } catch (ErrorTypeKindException e) {
        // Do nothing, per Issue #244.
      }
    } else {
      assert decl.isConstructorDeclaration();
      annotate(methodType.getReturnType(), decl.getAnnotations(), decl);
    }

    // Parameters
    processParameters(decl, elt, methodType);

    // Receiver
    if (decl.getReceiverParameter().isPresent()) {
      ReceiverParameter receiverParameter = decl.getReceiverParameter().get();
      if (methodType.getReceiverType() == null) {
        if (decl.isConstructorDeclaration()) {
          warn(
              receiverParameter,
              "parseParameter: constructor %s of a top-level class cannot have receiver"
                  + " annotations %s",
              methodType,
              decl.getReceiverParameter().get().getAnnotations());
        } else {
          warn(
              receiverParameter,
              "parseParameter: static method %s cannot have receiver annotations %s",
              methodType,
              decl.getReceiverParameter().get().getAnnotations());
        }
      } else {
        // Add declaration annotations.
        annotate(
            methodType.getReceiverType(),
            decl.getReceiverParameter().get().getAnnotations(),
            receiverParameter);
        // Add type annotations.
        annotate(
            methodType.getReceiverType(),
            decl.getReceiverParameter().get().getType(),
            decl.getReceiverParameter().get().getAnnotations(),
            receiverParameter);
      }
    }

    if (warnIfStubRedundantWithBytecode
        && methodType.toString().equals(origMethodType.toString())
        && fileType != AnnotationFileType.BUILTIN_STUB) {
      warn(
          decl,
          String.format(
              "redundant stub file specification for %s", ElementUtils.getQualifiedName(elt)));
    }

    // Store the type.
    putMerge(annotationFileAnnos.atypes, elt, methodType);
    if (fileType.isStub()) {
      typeParameters.removeAll(methodType.getTypeVariables());
    }

    return methodType.getTypeVariables();
  }

  /**
   * Process the parameters of a method or constructor declaration: copy their annotations to {@code
   * #annotationFileAnnos}.
   *
   * @param method a Method or Constructor declaration
   * @param elt ExecutableElement of {@code method}
   * @param methodType annotated type of {@code method}
   */
  private void processParameters(
      CallableDeclaration<?> method, ExecutableElement elt, AnnotatedExecutableType methodType) {
    List<Parameter> params = method.getParameters();
    List<? extends VariableElement> paramElts = elt.getParameters();
    List<? extends AnnotatedTypeMirror> paramTypes = methodType.getParameterTypes();

    for (int i = 0; i < methodType.getParameterTypes().size(); ++i) {
      VariableElement paramElt = paramElts.get(i);
      AnnotatedTypeMirror paramType = paramTypes.get(i);
      Parameter param = params.get(i);

      recordDeclAnnotation(paramElt, param.getAnnotations(), param);
      recordDeclAnnotation(paramElt, param.getType().getAnnotations(), param);

      if (param.isVarArgs()) {
        assert paramType.getKind() == TypeKind.ARRAY;
        // The "type" of param is actually the component type of the vararg.
        // For example, in "Object..." the type would be "Object".
        annotate(
            ((AnnotatedArrayType) paramType).getComponentType(),
            param.getType(),
            param.getAnnotations(),
            param);
        // The "VarArgsAnnotations" are those just before "...".
        annotate(paramType, param.getVarArgsAnnotations(), param);
      } else {
        annotate(paramType, param.getType(), param.getAnnotations(), param);
        putMerge(annotationFileAnnos.atypes, paramElt, paramType);
      }
    }
  }

  /**
   * Clear (remove) existing annotations on the type.
   *
   * <p>Stub files override annotations read from .class files. Using {@code replaceAnnotation}
   * usually achieves this; however, for annotations on type variables, it is sometimes necessary to
   * remove an existing annotation, leaving no annotation on the type variable. This method does so.
   *
   * @param atype the type to modify
   * @param typeDef the type from the annotation file, used only for diagnostic messages
   */
  @SuppressWarnings("unused") // for disabled warning message
  private void clearAnnotations(AnnotatedTypeMirror atype, Type typeDef) {
    // TODO: only produce output if the removed annotation isn't the top or default
    // annotation in the type hierarchy.  See https://tinyurl.com/cfissue/2759 .
    /*
    if (!atype.getAnnotations().isEmpty()) {
        stubWarnOverwritesBytecode(
                String.format(
                        "in file %s at line %s removed existing annotations on type: %s",
                        filename.substring(filename.lastIndexOf('/') + 1),
                        typeDef.getBegin().get().line,
                        atype.toString(true)));
    }
    */
    // Clear existing annotations, which only makes a difference for
    // type variables, but doesn't hurt in other cases.
    atype.clearAnnotations();
  }

  /**
   * Add the annotations from {@code type} to {@code atype}. Type annotations that parsed as
   * declaration annotations (i.e., type annotations in {@code declAnnos}) are applied to the
   * innermost component type.
   *
   * @param atype annotated type to which to add annotations
   * @param type parsed type
   * @param declAnnos annotations stored on the declaration of the variable with this type or null
   * @param astNode where to report errors
   */
  private void annotateAsArray(
      AnnotatedArrayType atype,
      ReferenceType type,
      @Nullable NodeList<AnnotationExpr> declAnnos,
      NodeWithRange<?> astNode) {
    annotateInnermostComponentType(atype, declAnnos, astNode);
    Type typeDef = type;
    AnnotatedTypeMirror currentAtype = atype;
    while (typeDef.isArrayType()) {
      if (currentAtype.getKind() != TypeKind.ARRAY) {
        warn(astNode, "Mismatched array lengths; atype: " + atype + "%n  type: " + type);
        return;
      }

      // handle generic type
      clearAnnotations(currentAtype, typeDef);

      List<AnnotationExpr> annotations = typeDef.getAnnotations();
      if (annotations != null) {
        annotate(currentAtype, annotations, astNode);
      }
      typeDef = ((com.github.javaparser.ast.type.ArrayType) typeDef).getComponentType();
      currentAtype = ((AnnotatedArrayType) currentAtype).getComponentType();
    }
    if (currentAtype.getKind() == TypeKind.ARRAY) {
      warn(astNode, "Mismatched array lengths; atype: " + atype + "%n  type: " + type);
    }
  }

  private ClassOrInterfaceType unwrapDeclaredType(Type type) {
    if (type instanceof ClassOrInterfaceType) {
      return (ClassOrInterfaceType) type;
    } else if (type instanceof ReferenceType && type.getArrayLevel() == 0) {
      return unwrapDeclaredType(type.getElementType());
    } else {
      return null;
    }
  }

  /**
   * Add to formal parameter {@code atype}:
   *
   * <ol>
   *   <li>the annotations from {@code typeDef}, and
   *   <li>any type annotations that parsed as declaration annotations (i.e., type annotations in
   *       {@code declAnnos}).
   * </ol>
   *
   * @param atype annotated type to which to add annotations
   * @param typeDef parsed type
   * @param declAnnos annotations stored on the declaration of the variable with this type, or null
   * @param astNode where to report errors
   */
  private void annotate(
      AnnotatedTypeMirror atype,
      Type typeDef,
      @Nullable NodeList<AnnotationExpr> declAnnos,
      NodeWithRange<?> astNode) {
    if (atype.getKind() == TypeKind.ARRAY) {
      if (typeDef instanceof ReferenceType) {
        annotateAsArray((AnnotatedArrayType) atype, (ReferenceType) typeDef, declAnnos, astNode);
      } else {
        warn(astNode, "expected ReferenceType but found: " + typeDef);
      }
      return;
    }

    clearAnnotations(atype, typeDef);

    // Primary annotations for the type of a variable declaration are not stored in typeDef, but
    // rather as declaration annotations (passed as declAnnos to this method).  But, if typeDef
    // is not the type of a variable, then the primary annotations are stored in typeDef.
    NodeList<AnnotationExpr> primaryAnnotations;
    if (typeDef.getAnnotations().isEmpty() && declAnnos != null) {
      primaryAnnotations = declAnnos;
    } else {
      primaryAnnotations = typeDef.getAnnotations();
    }
    if (atype.getKind() != TypeKind.WILDCARD) {
      // The primary annotation on a wildcard applies to the super or extends bound and
      // are added below.
      annotate(atype, primaryAnnotations, astNode);
    }

    switch (atype.getKind()) {
      case DECLARED:
        ClassOrInterfaceType declType = unwrapDeclaredType(typeDef);
        if (declType == null) {
          break;
        }
        AnnotatedDeclaredType adeclType = (AnnotatedDeclaredType) atype;
        // Process type arguments.
        if (declType.getTypeArguments().isPresent()
            && !declType.getTypeArguments().get().isEmpty()
            && !adeclType.getTypeArguments().isEmpty()) {
          if (declType.getTypeArguments().get().size() != adeclType.getTypeArguments().size()) {
            warn(
                astNode,
                String.format(
                    "Mismatch in type argument size between %s (%d) and %s (%d)",
                    declType,
                    declType.getTypeArguments().get().size(),
                    adeclType,
                    adeclType.getTypeArguments().size()));
            break;
          }
          for (int i = 0; i < declType.getTypeArguments().get().size(); ++i) {
            annotate(
                adeclType.getTypeArguments().get(i),
                declType.getTypeArguments().get().get(i),
                null,
                astNode);
          }
        }
        break;
      case WILDCARD:
        AnnotatedWildcardType wildcardType = (AnnotatedWildcardType) atype;
        // Ensure that the file also has a wildcard type, report an error otherwise
        if (!typeDef.isWildcardType()) {
          // We throw an error here, as otherwise we are just getting a generic cast error
          // on the very next line.
          warn(
              astNode,
              "Wildcard type <"
                  + atype
                  + "> does not match type in stubs file"
                  + filename
                  + ": <"
                  + typeDef
                  + ">"
                  + " while parsing "
                  + typeBeingParsed);
          return;
        }
        WildcardType wildcardDef = (WildcardType) typeDef;
        if (wildcardDef.getExtendedType().isPresent()) {
          annotate(
              wildcardType.getExtendsBound(), wildcardDef.getExtendedType().get(), null, astNode);
          annotate(wildcardType.getSuperBound(), primaryAnnotations, astNode);
        } else if (wildcardDef.getSuperType().isPresent()) {
          annotate(wildcardType.getSuperBound(), wildcardDef.getSuperType().get(), null, astNode);
          annotate(wildcardType.getExtendsBound(), primaryAnnotations, astNode);
        } else {
          annotate(atype, primaryAnnotations, astNode);
        }
        break;
      case TYPEVAR:
        // Add annotations from the declaration of the TypeVariable
        AnnotatedTypeVariable typeVarUse = (AnnotatedTypeVariable) atype;
        Types typeUtils = processingEnv.getTypeUtils();
        for (AnnotatedTypeVariable typePar : typeParameters) {
          if (typeUtils.isSameType(typePar.getUnderlyingType(), atype.getUnderlyingType())) {
            atypeFactory.replaceAnnotations(typePar.getUpperBound(), typeVarUse.getUpperBound());
            atypeFactory.replaceAnnotations(typePar.getLowerBound(), typeVarUse.getLowerBound());
          }
        }
        break;
      default:
        // No additional annotations to add.
    }
  }

  /**
   * Process the field declaration in decl: copy its annotations to {@code #annotationFileAnnos}.
   *
   * @param decl the declaration in the annotation file
   * @param elt the element representing that same declaration
   */
  private void processField(FieldDeclaration decl, VariableElement elt) {
    if (skipNode(decl)) {
      // Don't process private fields of the JDK.  They can't be referenced outside of the JDK
      // and might refer to types that are not accessible.
      return;
    }
    markAsFromStubFile(elt);
    recordDeclAnnotation(elt, decl.getAnnotations(), decl);
    // AnnotationFileParser parses all annotations in type annotation position as type annotations
    recordDeclAnnotation(elt, decl.getElementType().getAnnotations(), decl);
    AnnotatedTypeMirror fieldType = atypeFactory.fromElement(elt);

    VariableDeclarator fieldVarDecl = null;
    String eltName = elt.getSimpleName().toString();
    for (VariableDeclarator var : decl.getVariables()) {
      if (var.getName().toString().equals(eltName)) {
        fieldVarDecl = var;
        break;
      }
    }
    assert fieldVarDecl != null;
    annotate(fieldType, fieldVarDecl.getType(), decl.getAnnotations(), fieldVarDecl);
    putMerge(annotationFileAnnos.atypes, elt, fieldType);
  }

  /**
   * Adds the annotations present on the declaration of an enum constant to the ATM of that
   * constant.
   *
   * @param decl the enum constant, in Javaparser AST form (the source of annotations)
   * @param elt the enum constant declaration, as an element (the destination for annotations)
   */
  private void processEnumConstant(EnumConstantDeclaration decl, VariableElement elt) {
    markAsFromStubFile(elt);
    recordDeclAnnotation(elt, decl.getAnnotations(), decl);
    AnnotatedTypeMirror enumConstType = atypeFactory.fromElement(elt);
    annotate(enumConstType, decl.getAnnotations(), decl);
    putMerge(annotationFileAnnos.atypes, elt, enumConstType);
  }

  /**
   * Returns the innermost component type of {@code type}.
   *
   * @param type array type
   * @return the innermost component type of {@code type}
   */
  private AnnotatedTypeMirror innermostComponentType(AnnotatedArrayType type) {
    AnnotatedTypeMirror componentType = type;
    while (componentType.getKind() == TypeKind.ARRAY) {
      componentType = ((AnnotatedArrayType) componentType).getComponentType();
    }
    return componentType;
  }

  /**
   * Adds {@code annotations} to the innermost component type of {@code type}.
   *
   * @param type array type
   * @param annotations annotations to add
   * @param astNode where to report errors
   */
  private void annotateInnermostComponentType(
      AnnotatedArrayType type, List<AnnotationExpr> annotations, NodeWithRange<?> astNode) {
    annotate(innermostComponentType(type), annotations, astNode);
  }

  /**
   * Annotate the type with the given type annotations, removing any existing annotations from the
   * same qualifier hierarchies.
   *
   * @param type the type to annotate
   * @param annotations the new annotations for the type
   * @param astNode where to report errors
   */
  private void annotate(
      AnnotatedTypeMirror type, List<AnnotationExpr> annotations, NodeWithRange<?> astNode) {
    if (annotations == null) {
      return;
    }
    for (AnnotationExpr annotation : annotations) {
      AnnotationMirror annoMirror = getAnnotation(annotation, allAnnotations);
      if (annoMirror != null) {
        type.replaceAnnotation(annoMirror);
      } else {
        // TODO: Maybe always warn here.  It's so easy to forget an import statement and
        // have an annotation silently ignored.
        stubWarnNotFound(astNode, "Unknown annotation " + annotation);
      }
    }
  }

  /**
   * Adds to {@code annotationFileAnnos} all the annotations in {@code annotations} that are
   * applicable to {@code elt}'s location. For example, if an annotation is a type annotation but
   * {@code elt} is a field declaration, the type annotation will be ignored.
   *
   * @param elt the element to be annotated
   * @param annotations set of annotations that may be applicable to elt
   * @param astNode where to report errors
   */
  private void recordDeclAnnotation(
      Element elt, List<AnnotationExpr> annotations, NodeWithRange<?> astNode) {
    if (annotations == null || annotations.isEmpty()) {
      return;
    }
    Set<AnnotationMirror> annos = AnnotationUtils.createAnnotationSet();
    for (AnnotationExpr annotation : annotations) {
      AnnotationMirror annoMirror = getAnnotation(annotation, allAnnotations);
      if (annoMirror != null) {
        // The @Target annotation on `annotation`/`annoMirror`
        Target target = annoMirror.getAnnotationType().asElement().getAnnotation(Target.class);
        // Only add the declaration annotation if the annotation applies to the element.
        if (AnnotationUtils.getElementKindsForTarget(target).contains(elt.getKind())) {
          // `annoMirror` is applicable to `elt`
          annos.add(annoMirror);
        }
      } else {
        // TODO: Maybe always warn here.  It's so easy to forget an import statement and
        // have an annotation silently ignored.
        stubWarnNotFound(astNode, String.format("Unknown annotation %s", annotation));
      }
    }
    String eltName = ElementUtils.getQualifiedName(elt);
    putOrAddToDeclAnnos(eltName, annos);
  }

  /**
   * Adds the declaration annotation {@code @FromStubFile} to {@link #annotationFileAnnos}, unless
   * we are parsing the JDK as a stub file.
   *
   * @param elt an element to be annotated as {@code @FromStubFile}
   */
  private void markAsFromStubFile(Element elt) {
    if (fileType == AnnotationFileType.AJAVA || fileType == AnnotationFileType.JDK_STUB) {
      return;
    }
    putOrAddToDeclAnnos(
        ElementUtils.getQualifiedName(elt), Collections.singleton(fromStubFileAnno));
  }

  private void annotateTypeParameters(
      BodyDeclaration<?> decl, // for debugging
      Object elt, // for debugging; TypeElement or ExecutableElement
      List<? extends AnnotatedTypeMirror> typeArguments,
      List<TypeParameter> typeParameters) {
    if (typeParameters == null) {
      return;
    }

    if (typeParameters.size() != typeArguments.size()) {
      String msg =
          String.format(
              "annotateTypeParameters: mismatched sizes:  typeParameters (size %d)=%s; "
                  + " typeArguments (size %d)=%s;  decl=%s;  elt=%s (%s).",
              typeParameters.size(),
              typeParameters,
              typeArguments.size(),
              typeArguments,
              decl.toString().replace(LINE_SEPARATOR, " "),
              elt.toString().replace(LINE_SEPARATOR, " "),
              elt.getClass());
      if (!debugAnnotationFileParser) {
        msg = msg + "; for more details, run with -AstubDebug";
      }
      warn(decl, msg);
      return;
    }
    for (int i = 0; i < typeParameters.size(); ++i) {
      TypeParameter param = typeParameters.get(i);
      AnnotatedTypeVariable paramType = (AnnotatedTypeVariable) typeArguments.get(i);

      if (param.getTypeBound() == null || param.getTypeBound().isEmpty()) {
        // No bound so annotations are both lower and upper bounds
        annotate(paramType, param.getAnnotations(), param);
      } else if (param.getTypeBound() != null && !param.getTypeBound().isEmpty()) {
        annotate(paramType.getLowerBound(), param.getAnnotations(), param);
        annotate(paramType.getUpperBound(), param.getTypeBound().get(0), null, param);
        if (param.getTypeBound().size() > 1) {
          // TODO: add support for intersection types
          stubWarnNotFound(param, "Annotations on intersection types are not yet supported");
        }
      }
      putMerge(annotationFileAnnos.atypes, paramType.getUnderlyingType().asElement(), paramType);
    }
  }

  /**
   * Returns a pair of mappings. For each member declaration of the JavaParser type declaration
   * {@code typeDecl}:
   *
   * <ul>
   *   <li>If {@code typeElt} contains a member element for it, the first mapping maps the member
   *       element to it.
   *   <li>If it is a fake override, the second mapping maps each element it overrides to it.
   *   <li>Otherwise, does nothing.
   * </ul>
   *
   * This method does not read or write the field {@link #annotationFileAnnos}.
   *
   * @param typeDecl a JavaParser type declaration
   * @param typeElt the javac element for {@code typeDecl}
   * @return two mappings: from javac elements to their JavaParser declaration, and from javac
   *     elements to fake overrides of them
   * @param astNode where to report errors
   */
  private Pair<Map<Element, BodyDeclaration<?>>, Map<Element, List<BodyDeclaration<?>>>> getMembers(
      TypeDeclaration<?> typeDecl, TypeElement typeElt, NodeWithRange<?> astNode) {
    assert (typeElt.getSimpleName().contentEquals(typeDecl.getNameAsString())
            || typeDecl.getNameAsString().endsWith("$" + typeElt.getSimpleName()))
        : String.format("%s  %s", typeElt.getSimpleName(), typeDecl.getName());

    Map<Element, BodyDeclaration<?>> elementsToDecl = new LinkedHashMap<>();
    Map<Element, List<BodyDeclaration<?>>> fakeOverrideDecls = new LinkedHashMap<>();

    for (BodyDeclaration<?> member : typeDecl.getMembers()) {
      putNewElement(
          elementsToDecl, fakeOverrideDecls, typeElt, member, typeDecl.getNameAsString(), astNode);
    }
    // For an enum type declaration, also add the enum constants
    if (typeDecl instanceof EnumDeclaration) {
      EnumDeclaration enumDecl = (EnumDeclaration) typeDecl;
      // getEntries() gives the list of enum constant declarations
      for (BodyDeclaration<?> member : enumDecl.getEntries()) {
        putNewElement(
            elementsToDecl,
            fakeOverrideDecls,
            typeElt,
            member,
            typeDecl.getNameAsString(),
            astNode);
      }
    }

    return Pair.of(elementsToDecl, fakeOverrideDecls);
  }

  // Used only by getMembers().
  /**
   * If {@code typeElt} contains an element for {@code member}, adds to {@code elementsToDecl} a
   * mapping from member's element to member. Does nothing if a mapping already exists.
   *
   * <p>Otherwise (if there is no element for {@code member}), adds to {@code fakeOverrideDecls}
   * zero or more mappings. Each mapping is from an element that {@code member} would override to
   * {@code member}.
   *
   * <p>This method does not read or write field {@link annotationFileAnnos}.
   *
   * @param elementsToDecl the mapping that is side-effected by this method
   * @param fakeOverrideDecls fake overrides, also side-effected by this method
   * @param typeElt the class in which {@code member} is declared
   * @param member the stub file declaration of a method
   * @param typeDeclName used only for debugging
   * @param astNode where to report errors
   */
  private void putNewElement(
      Map<Element, BodyDeclaration<?>> elementsToDecl,
      Map<Element, List<BodyDeclaration<?>>> fakeOverrideDecls,
      TypeElement typeElt,
      BodyDeclaration<?> member,
      String typeDeclName,
      NodeWithRange<?> astNode) {
    if (member instanceof MethodDeclaration) {
      MethodDeclaration method = (MethodDeclaration) member;
      Element elt = findElement(typeElt, method, /*noWarn=*/ true);
      if (elt != null) {
        putIfAbsent(elementsToDecl, elt, method);
      } else {
        ExecutableElement overriddenMethod = fakeOverriddenMethod(typeElt, method);
        if (overriddenMethod == null) {
          // Didn't find the element and it isn't a fake override.  Issue a warning.
          findElement(typeElt, method, /*noWarn=*/ false);
        } else {
          List<BodyDeclaration<?>> l =
              fakeOverrideDecls.computeIfAbsent(overriddenMethod, __ -> new ArrayList<>());
          l.add(member);
        }
      }
    } else if (member instanceof ConstructorDeclaration) {
      Element elt = findElement(typeElt, (ConstructorDeclaration) member);
      if (elt != null) {
        putIfAbsent(elementsToDecl, elt, member);
      }
    } else if (member instanceof FieldDeclaration) {
      FieldDeclaration fieldDecl = (FieldDeclaration) member;
      for (VariableDeclarator var : fieldDecl.getVariables()) {
        Element varelt = findElement(typeElt, var);
        if (varelt != null) {
          putIfAbsent(elementsToDecl, varelt, fieldDecl);
        }
      }
    } else if (member instanceof EnumConstantDeclaration) {
      Element elt = findElement(typeElt, (EnumConstantDeclaration) member, astNode);
      if (elt != null) {
        putIfAbsent(elementsToDecl, elt, member);
      }
    } else if (member instanceof ClassOrInterfaceDeclaration) {
      Element elt = findElement(typeElt, (ClassOrInterfaceDeclaration) member);
      if (elt != null) {
        putIfAbsent(elementsToDecl, elt, member);
      }
    } else if (member instanceof EnumDeclaration) {
      Element elt = findElement(typeElt, (EnumDeclaration) member);
      if (elt != null) {
        putIfAbsent(elementsToDecl, elt, member);
      }
    } else {
      stubDebug(
          String.format("Ignoring element of type %s in %s", member.getClass(), typeDeclName));
    }
  }

  /**
   * Given a method declaration that does not correspond to an element, returns the method it
   * directly overrides or implements. As Java does, this prefers a method in a superclass to one in
   * an interface.
   *
   * <p>As with regular overrides, the parameter types must be exact matches; contravariance is not
   * permitted.
   *
   * @param typeElt the type in which the method appears
   * @param methodDecl the method declaration that does not correspond to an element
   * @return the methods that the given method declaration would override, or null if none
   */
  private @Nullable ExecutableElement fakeOverriddenMethod(
      TypeElement typeElt, MethodDeclaration methodDecl) {
    for (Element elt : typeElt.getEnclosedElements()) {
      if (elt.getKind() != ElementKind.METHOD) {
        continue;
      }
      ExecutableElement candidate = (ExecutableElement) elt;
      if (!candidate.getSimpleName().contentEquals(methodDecl.getName().getIdentifier())) {
        continue;
      }
      List<? extends VariableElement> candidateParams = candidate.getParameters();
      if (sameTypes(candidateParams, methodDecl.getParameters())) {
        return candidate;
      }
    }

    TypeElement superType = ElementUtils.getSuperClass(typeElt);
    if (superType != null) {
      ExecutableElement result = fakeOverriddenMethod(superType, methodDecl);
      if (result != null) {
        return result;
      }
    }

    for (TypeMirror interfaceTypeMirror : typeElt.getInterfaces()) {
      TypeElement interfaceElement = (TypeElement) ((DeclaredType) interfaceTypeMirror).asElement();
      ExecutableElement result = fakeOverriddenMethod(interfaceElement, methodDecl);
      if (result != null) {
        return result;
      }
    }

    return null;
  }

  /**
   * Returns true if the two signatures (represented as lists of formal parameters) are the same. No
   * contravariance is permitted.
   *
   * @param javacParams parameter list in javac form
   * @param javaParserParams parameter list in JavaParser form
   * @return true if the two signatures are the same
   */
  private boolean sameTypes(
      List<? extends VariableElement> javacParams, NodeList<Parameter> javaParserParams) {
    if (javacParams.size() != javaParserParams.size()) {
      return false;
    }
    for (int i = 0; i < javacParams.size(); i++) {
      TypeMirror javacType = javacParams.get(i).asType();
      Parameter javaParserParam = javaParserParams.get(i);
      Type javaParserType = javaParserParam.getType();
      if (javacType.getKind() == TypeKind.TYPEVAR) {
        // TODO: Hack, need to viewpoint-adapt.
        javacType = ((TypeVariable) javacType).getUpperBound();
      }
      if (!sameType(javacType, javaParserType)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Returns true if the two types are the same.
   *
   * @param javacType type in javac form
   * @param javaParserType type in JavaParser form
   * @return true if the two types are the same
   */
  private boolean sameType(TypeMirror javacType, Type javaParserType) {

    switch (javacType.getKind()) {
      case BOOLEAN:
        return javaParserType.equals(PrimitiveType.booleanType());
      case BYTE:
        return javaParserType.equals(PrimitiveType.byteType());
      case CHAR:
        return javaParserType.equals(PrimitiveType.charType());
      case DOUBLE:
        return javaParserType.equals(PrimitiveType.doubleType());
      case FLOAT:
        return javaParserType.equals(PrimitiveType.floatType());
      case INT:
        return javaParserType.equals(PrimitiveType.intType());
      case LONG:
        return javaParserType.equals(PrimitiveType.longType());
      case SHORT:
        return javaParserType.equals(PrimitiveType.shortType());

      case DECLARED:
      case TYPEVAR:
        if (!(javaParserType instanceof ClassOrInterfaceType)) {
          return false;
        }
        com.sun.tools.javac.code.Type javacTypeInternal = (com.sun.tools.javac.code.Type) javacType;
        ClassOrInterfaceType javaParserClassType = (ClassOrInterfaceType) javaParserType;

        // Use asString() because toString() includes annotations.
        String javaParserString = javaParserClassType.asString();
        Element javacElement = javacTypeInternal.asElement();
        // Check both fully-qualified name and simple name.
        return javacElement.toString().equals(javaParserString)
            || javacElement.getSimpleName().contentEquals(javaParserString);

      case ARRAY:
        return javaParserType.isArrayType()
            && sameType(
                ((ArrayType) javacType).getComponentType(),
                javaParserType.asArrayType().getComponentType());

      default:
        throw new BugInCF("Unhandled type %s of kind %s", javacType, javacType.getKind());
    }
  }

  /**
   * Process a fake override: copy its annotations to the fake overrides part of {@code
   * #annotationFileAnnos}.
   *
   * @param element a real element
   * @param decl a fake override of the element
   * @param fakeLocation where the fake override was defined
   */
  private void processFakeOverride(
      ExecutableElement element, CallableDeclaration<?> decl, TypeElement fakeLocation) {
    // This is a fresh type, which this code may side-effect.
    AnnotatedExecutableType methodType = atypeFactory.getAnnotatedType(element);

    // Here is a hacky solution that does not use the visitor.  It just handles the return type.
    // TODO: Walk the type and the declaration, copying annotations from the declaration to the
    // element.  I think PR #3977 has a visitor that does that, which I should use after it is
    // merged.

    // The annotations on the method.  These include type annotations on the return type.
    NodeList<AnnotationExpr> annotations = decl.getAnnotations();
    annotate(methodType.getReturnType(), ((MethodDeclaration) decl).getType(), annotations, decl);

    List<Pair<TypeMirror, AnnotatedTypeMirror>> l =
        annotationFileAnnos.fakeOverrides.computeIfAbsent(element, __ -> new ArrayList<>());
    l.add(Pair.of(fakeLocation.asType(), methodType));
  }

  /**
   * Return the annotated type corresponding to {@code type}, or null if none exists. More
   * specifically, returns the element of {@code types} whose name matches {@code type}.
   *
   * @param type the type to search for
   * @param types the list of AnnotatedDeclaredTypes to search in
   * @param astNode where to report errors
   * @return the annotated type in {@code types} corresponding to {@code type}, or null if none
   *     exists
   */
  private @Nullable AnnotatedDeclaredType findAnnotatedType(
      ClassOrInterfaceType type, List<AnnotatedDeclaredType> types, NodeWithRange<?> astNode) {
    String typeString = type.getNameAsString();
    for (AnnotatedDeclaredType supertype : types) {
      if (supertype.getUnderlyingType().asElement().getSimpleName().contentEquals(typeString)) {
        return supertype;
      }
    }
    stubWarnNotFound(astNode, "Supertype " + typeString + " not found");
    if (debugAnnotationFileParser) {
      stubDebug("Supertypes that were searched:");
      for (AnnotatedDeclaredType supertype : types) {
        stubDebug(String.format("  %s", supertype));
      }
    }
    return null;
  }

  /**
   * Looks for the nested type element in the typeElt and returns it if the element has the same
   * name as provided class or interface declaration. In case nested element is not found it returns
   * null.
   *
   * @param typeElt an element where nested type element should be looked for
   * @param ciDecl class or interface declaration which name should be found among nested elements
   *     of the typeElt
   * @return nested in typeElt element with the name of the class or interface or null if nested
   *     element is not found
   */
  private @Nullable Element findElement(TypeElement typeElt, ClassOrInterfaceDeclaration ciDecl) {
    final String wantedClassOrInterfaceName = ciDecl.getNameAsString();
    for (TypeElement typeElement : ElementUtils.getAllTypeElementsIn(typeElt)) {
      if (wantedClassOrInterfaceName.equals(typeElement.getSimpleName().toString())) {
        return typeElement;
      }
    }

    stubWarnNotFound(
        ciDecl, "Class/interface " + wantedClassOrInterfaceName + " not found in type " + typeElt);
    if (debugAnnotationFileParser) {
      stubDebug(String.format("  Here are the type declarations of %s:", typeElt));
      for (TypeElement method : ElementFilter.typesIn(typeElt.getEnclosedElements())) {
        stubDebug(String.format("    %s", method));
      }
    }
    return null;
  }

  /**
   * Looks for the nested enum element in the typeElt and returns it if the element has the same
   * name as provided enum declaration. In case nested element is not found it returns null.
   *
   * @param typeElt an element where nested enum element should be looked for
   * @param enumDecl enum declaration which name should be found among nested elements of the
   *     typeElt
   * @return nested in typeElt enum element with the name of the provided enum or null if nested
   *     element is not found
   */
  private @Nullable Element findElement(TypeElement typeElt, EnumDeclaration enumDecl) {
    final String wantedEnumName = enumDecl.getNameAsString();
    for (TypeElement typeElement : ElementUtils.getAllTypeElementsIn(typeElt)) {
      if (wantedEnumName.equals(typeElement.getSimpleName().toString())) {
        return typeElement;
      }
    }

    stubWarnNotFound(enumDecl, "Enum " + wantedEnumName + " not found in type " + typeElt);
    if (debugAnnotationFileParser) {
      stubDebug(String.format("  Here are the type declarations of %s:", typeElt));
      for (TypeElement method : ElementFilter.typesIn(typeElt.getEnclosedElements())) {
        stubDebug(String.format("    %s", method));
      }
    }
    return null;
  }

  /**
   * Looks for an enum constant element in the typeElt and returns it if the element has the same
   * name as provided. In case enum constant element is not found it returns null.
   *
   * @param typeElt type element where enum constant element should be looked for
   * @param enumConstDecl the declaration of the enum constant
   * @param astNode where to report errors
   * @return enum constant element in typeElt with the provided name or null if enum constant
   *     element is not found
   */
  private @Nullable VariableElement findElement(
      TypeElement typeElt, EnumConstantDeclaration enumConstDecl, NodeWithRange<?> astNode) {
    final String enumConstName = enumConstDecl.getNameAsString();
    return findFieldElement(typeElt, enumConstName, astNode);
  }

  /**
   * Looks for a method element in {@code typeElt} that has the same name and formal parameter types
   * as {@code methodDecl}. Returns null, and possibly issues a warning, if no such method element
   * is found.
   *
   * @param typeElt type element where method element should be looked for
   * @param methodDecl method declaration with signature that should be found among methods in the
   *     typeElt
   * @param noWarn if true, don't issue a warning if the element is not found
   * @return method element in typeElt with the same signature as the provided method declaration or
   *     null if method element is not found
   */
  private @Nullable ExecutableElement findElement(
      TypeElement typeElt, MethodDeclaration methodDecl, boolean noWarn) {
    if (skipNode(methodDecl)) {
      return null;
    }
    final String wantedMethodName = methodDecl.getNameAsString();
    final int wantedMethodParams =
        (methodDecl.getParameters() == null) ? 0 : methodDecl.getParameters().size();
    final String wantedMethodString = AnnotationFileUtil.toString(methodDecl);
    for (ExecutableElement method : ElementFilter.methodsIn(typeElt.getEnclosedElements())) {
      if (wantedMethodParams == method.getParameters().size()
          && wantedMethodName.contentEquals(method.getSimpleName().toString())
          && ElementUtils.getSimpleSignature(method).equals(wantedMethodString)) {
        return method;
      }
    }
    if (!noWarn) {
      if (methodDecl.getAccessSpecifier() == AccessSpecifier.PACKAGE_PRIVATE) {
        // This might be a false positive warning.  The stub parser permits a stub file to
        // omit the access specifier, but package-private methods aren't in the TypeElement.
        stubWarnNotFound(
            methodDecl,
            "Package-private method "
                + wantedMethodString
                + " not found in type "
                + typeElt
                + System.lineSeparator()
                + "If the method is not package-private, add an access specifier in the stub file"
                + " and use pass -AstubDebug to receive a more useful error message.");
      } else {
        stubWarnNotFound(
            methodDecl, "Method " + wantedMethodString + " not found in type " + typeElt);
        if (debugAnnotationFileParser) {
          stubDebug(String.format("  Here are the methods of %s:", typeElt));
          for (ExecutableElement method : ElementFilter.methodsIn(typeElt.getEnclosedElements())) {
            stubDebug(String.format("    %s", method));
          }
        }
      }
    }
    return null;
  }

  /**
   * Looks for a constructor element in the typeElt and returns it if the element has the same
   * signature as provided constructor declaration. In case constructor element is not found it
   * returns null.
   *
   * @param typeElt type element where constructor element should be looked for
   * @param constructorDecl constructor declaration with signature that should be found among
   *     constructors in the typeElt
   * @return constructor element in typeElt with the same signature as the provided constructor
   *     declaration or null if constructor element is not found
   */
  private @Nullable ExecutableElement findElement(
      TypeElement typeElt, ConstructorDeclaration constructorDecl) {
    if (skipNode(constructorDecl)) {
      return null;
    }
    final int wantedMethodParams =
        (constructorDecl.getParameters() == null) ? 0 : constructorDecl.getParameters().size();
    final String wantedMethodString = AnnotationFileUtil.toString(constructorDecl);
    for (ExecutableElement method : ElementFilter.constructorsIn(typeElt.getEnclosedElements())) {
      if (wantedMethodParams == method.getParameters().size()
          && ElementUtils.getSimpleSignature(method).equals(wantedMethodString)) {
        return method;
      }
    }

    stubWarnNotFound(
        constructorDecl, "Constructor " + wantedMethodString + " not found in type " + typeElt);
    if (debugAnnotationFileParser) {
      for (ExecutableElement method : ElementFilter.constructorsIn(typeElt.getEnclosedElements())) {
        stubDebug(String.format("  %s", method));
      }
    }
    return null;
  }

  /**
   * Returns the element for the given variable.
   *
   * @param typeElt the type in which the variable is contained
   * @param variable the variable whose element to return
   * @return the element for the given variable
   */
  private VariableElement findElement(TypeElement typeElt, VariableDeclarator variable) {
    final String fieldName = variable.getNameAsString();
    return findFieldElement(typeElt, fieldName, variable);
  }

  /**
   * Looks for a field element in the typeElt and returns it if the element has the same name as
   * provided. In case field element is not found it returns null.
   *
   * @param typeElt type element where field element should be looked for
   * @param fieldName field name that should be found
   * @param astNode where to report errors
   * @return field element in typeElt with the provided name or null if field element is not found
   */
  private @Nullable VariableElement findFieldElement(
      TypeElement typeElt, String fieldName, NodeWithRange<?> astNode) {
    for (VariableElement field : ElementUtils.getAllFieldsIn(typeElt, elements)) {
      // field.getSimpleName() is a CharSequence, not a String
      if (fieldName.equals(field.getSimpleName().toString())) {
        return field;
      }
    }

    stubWarnNotFound(astNode, "Field " + fieldName + " not found in type " + typeElt);
    if (debugAnnotationFileParser) {
      for (VariableElement field : ElementFilter.fieldsIn(typeElt.getEnclosedElements())) {
        stubDebug(String.format("  %s", field));
      }
    }
    return null;
  }

  /**
   * Given a fully-qualified type name, return a TypeElement for it, or null if none exists. Also
   * cache in importedTypes.
   *
   * @param name a fully-qualified type name
   * @return a TypeElement for the name, or null
   */
  private @Nullable TypeElement getTypeElementOrNull(@FullyQualifiedName String name) {
    TypeElement typeElement = elements.getTypeElement(name);
    if (typeElement != null) {
      importedTypes.put(name, typeElement);
    }
    // for debugging: warn("getTypeElementOrNull(%s) => %s", name, typeElement);
    return typeElement;
  }

  /**
   * Get the type element for the given fully-qualified type name. If none is found, issue a warning
   * and return null.
   *
   * @param typeName a type name
   * @param msg a warning message to issue if the type element for {@code typeName} cannot be found
   * @param astNode where to report errors
   * @return the type element for the given fully-qualified type name, or null
   */
  private TypeElement getTypeElement(
      @FullyQualifiedName String typeName, String msg, NodeWithRange<?> astNode) {
    TypeElement classElement = elements.getTypeElement(typeName);
    if (classElement == null) {
      stubWarnNotFound(astNode, msg + ": " + typeName);
    }
    return classElement;
  }

  /**
   * Returns the element for the given package.
   *
   * @param packageName the package's name
   * @param astNode where to report errors
   * @return the element for the given package
   */
  private PackageElement findPackage(String packageName, NodeWithRange<?> astNode) {
    PackageElement packageElement = elements.getPackageElement(packageName);
    if (packageElement == null) {
      stubWarnNotFound(astNode, "Imported package not found: " + packageName);
    }
    return packageElement;
  }

  /**
   * Returns true if one of the annotations is {@link AnnotatedFor} and this checker is in its list
   * of checkers. If none of the annotations are {@code AnnotatedFor}, then also return true.
   *
   * @param annotations a list of JavaParser annotations
   * @return true if one of the annotations is {@link AnnotatedFor} and its list of checkers does
   *     not contain this checker
   */
  private boolean isAnnotatedForThisChecker(List<AnnotationExpr> annotations) {
    if (fileType == AnnotationFileType.JDK_STUB) {
      // The JDK stubs have purity annotations that should be read for all checkers.
      // TODO: Parse the JDK stubs, but only save the declaration annotations.
      return true;
    }
    for (AnnotationExpr ae : annotations) {
      if (ae.getNameAsString().equals("AnnotatedFor")
          || ae.getNameAsString().equals("org.checkerframework.framework.qual.AnnotatedFor")) {
        AnnotationMirror af = getAnnotation(ae, allAnnotations);
        if (atypeFactory.areSameByClass(af, AnnotatedFor.class)) {
          return atypeFactory.doesAnnotatedForApplyToThisChecker(af);
        }
      }
    }
    return true;
  }

  /**
   * Convert {@code annotation} into an AnnotationMirror. Returns null if the annotation isn't
   * supported by the checker or if some error occurred while converting it.
   *
   * @param annotation syntax tree for an annotation
   * @param allAnnotations map from simple name to annotation definition; side-effected by this
   *     method
   * @return the AnnotationMirror for the annotation, or null if it cannot be built
   */
  private @Nullable AnnotationMirror getAnnotation(
      AnnotationExpr annotation, Map<String, TypeElement> allAnnotations) {

    @SuppressWarnings("signature") // https://tinyurl.com/cfissue/3094
    @FullyQualifiedName String annoNameFq = annotation.getNameAsString();
    TypeElement annoTypeElt = allAnnotations.get(annoNameFq);
    if (annoTypeElt == null) {
      // If the annotation was not imported, then #getImportedAnnotations did not add it to the
      // allAnnotations field. This code adds the annotation when it is encountered (i.e. here).
      // Note that this does not call AnnotationFileParser#getTypeElement to avoid a spurious
      // diagnostic if the annotation is actually unknown.
      annoTypeElt = elements.getTypeElement(annoNameFq);
      if (annoTypeElt == null) {
        // Not a supported annotation -> ignore
        return null;
      }
      putAllNew(allAnnotations, createNameToAnnotationMap(Collections.singletonList(annoTypeElt)));
    }
    @SuppressWarnings("signature") // not anonymous, so name is not empty
    @CanonicalName String annoName = annoTypeElt.getQualifiedName().toString();

    if (annotation instanceof MarkerAnnotationExpr) {
      return AnnotationBuilder.fromName(elements, annoName);
    } else if (annotation instanceof NormalAnnotationExpr) {
      NormalAnnotationExpr nrmanno = (NormalAnnotationExpr) annotation;
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, annoName);
      List<MemberValuePair> pairs = nrmanno.getPairs();
      if (pairs != null) {
        for (MemberValuePair mvp : pairs) {
          String member = mvp.getNameAsString();
          Expression exp = mvp.getValue();
          try {
            builderAddElement(builder, member, exp);
          } catch (AnnotationFileParserException e) {
            warn(
                exp,
                "For annotation %s, could not add  %s=%s  because %s",
                annotation,
                member,
                exp,
                e.getMessage());
            return null;
          }
        }
      }
      return builder.build();
    } else if (annotation instanceof SingleMemberAnnotationExpr) {
      SingleMemberAnnotationExpr sglanno = (SingleMemberAnnotationExpr) annotation;
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, annoName);
      Expression valExpr = sglanno.getMemberValue();
      try {
        builderAddElement(builder, "value", valExpr);
      } catch (AnnotationFileParserException e) {
        warn(
            valExpr,
            "For annotation %s, could not add  value=%s  because %s",
            annotation,
            valExpr,
            e.getMessage());
        return null;
      }
      return builder.build();
    } else {
      throw new BugInCF("AnnotationFileParser: unknown annotation type: " + annotation);
    }
  }

  /**
   * Returns the value of {@code expr}.
   *
   * @param name the name of an annotation element/argument, used for diagnostic messages
   * @param expr the expression to determine the value of
   * @param valueKind the type of the result
   * @return the value of {@code expr}
   * @throws AnnotationFileParserException if a problem occurred getting the value
   */
  private Object getValueOfExpressionInAnnotation(String name, Expression expr, TypeKind valueKind)
      throws AnnotationFileParserException {
    if (expr instanceof FieldAccessExpr || expr instanceof NameExpr) {
      VariableElement elem;
      if (expr instanceof NameExpr) {
        elem = findVariableElement((NameExpr) expr);
      } else {
        elem = findVariableElement((FieldAccessExpr) expr);
      }
      if (elem == null) {
        throw new AnnotationFileParserException(String.format("variable %s not found", expr));
      }
      Object value = elem.getConstantValue() != null ? elem.getConstantValue() : elem;
      if (value instanceof Number) {
        return convert((Number) value, valueKind);
      } else {
        return value;
      }
    } else if (expr instanceof StringLiteralExpr) {
      return ((StringLiteralExpr) expr).asString();
    } else if (expr instanceof BooleanLiteralExpr) {
      return ((BooleanLiteralExpr) expr).getValue();
    } else if (expr instanceof CharLiteralExpr) {
      return convert((int) ((CharLiteralExpr) expr).asChar(), valueKind);
    } else if (expr instanceof DoubleLiteralExpr) {
      // No conversion needed if the expression is a double, the annotation value must be a
      // double, too.
      return ((DoubleLiteralExpr) expr).asDouble();
    } else if (expr instanceof IntegerLiteralExpr) {
      return convert(((IntegerLiteralExpr) expr).asNumber(), valueKind);
    } else if (expr instanceof LongLiteralExpr) {
      return convert(((LongLiteralExpr) expr).asNumber(), valueKind);
    } else if (expr instanceof UnaryExpr) {
      switch (expr.toString()) {
          // Special-case the minimum values.  Separately parsing a "-" and a value
          // doesn't correctly handle the minimum values, because the absolute value of
          // the smallest member of an integral type is larger than the largest value.
        case "-9223372036854775808L":
        case "-9223372036854775808l":
          return convert(Long.MIN_VALUE, valueKind, false);
        case "-2147483648":
          return convert(Integer.MIN_VALUE, valueKind, false);
        default:
          if (((UnaryExpr) expr).getOperator() == UnaryExpr.Operator.MINUS) {
            Object value =
                getValueOfExpressionInAnnotation(
                    name, ((UnaryExpr) expr).getExpression(), valueKind);
            if (value instanceof Number) {
              return convert((Number) value, valueKind, true);
            }
          }
          throw new AnnotationFileParserException(
              "unexpected Unary annotation expression: " + expr);
      }
    } else if (expr instanceof ClassExpr) {
      ClassExpr classExpr = (ClassExpr) expr;
      @SuppressWarnings("signature") // Type.toString(): @FullyQualifiedName
      @FullyQualifiedName String className = classExpr.getType().toString();
      if (importedTypes.containsKey(className)) {
        return importedTypes.get(className).asType();
      }
      TypeElement typeElement = findTypeOfName(className);
      if (typeElement == null) {
        throw new AnnotationFileParserException("unknown class name " + className);
      }

      return typeElement.asType();
    } else if (expr instanceof NullLiteralExpr) {
      throw new AnnotationFileParserException("Illegal annotation value null, for " + name);
    } else {
      throw new AnnotationFileParserException("Unexpected annotation expression: " + expr);
    }
  }

  /**
   * Returns the TypeElement with the name {@code name}, if one exists. Otherwise, checks the class
   * and package of {@code typeBeingParsed} for a class named {@code name}.
   *
   * @param name classname (simple, or Outer.Inner, or fully-qualified)
   * @return the TypeElement for {@code name}, or null if not found
   */
  @SuppressWarnings("signature:argument") // string concatenation
  private @Nullable TypeElement findTypeOfName(@FullyQualifiedName String name) {
    String packageName = typeBeingParsed.packageName;
    String packagePrefix = (packageName == null) ? "" : packageName + ".";

    // warn("findTypeOfName(%s), typeBeingParsed %s %s", name, packageName, enclosingClass);

    // As soon as typeElement is set to a non-null value, it will be returned.
    TypeElement typeElement = getTypeElementOrNull(name);
    if (typeElement == null && packageName != null) {
      typeElement = getTypeElementOrNull(packagePrefix + name);
    }
    String enclosingClass = typeBeingParsed.className;
    while (typeElement == null && enclosingClass != null) {
      typeElement = getTypeElementOrNull(packagePrefix + enclosingClass + "." + name);
      int lastDot = enclosingClass.lastIndexOf('.');
      if (lastDot == -1) {
        break;
      } else {
        enclosingClass = enclosingClass.substring(0, lastDot);
      }
    }
    if (typeElement == null && !"java.lang".equals(packageName)) {
      typeElement = getTypeElementOrNull("java.lang." + name);
    }
    return typeElement;
  }

  /**
   * Converts {@code number} to {@code expectedKind}.
   *
   * <pre><code>
   * &nbsp; @interface Anno { long value(); }
   * &nbsp; @Anno(1)
   * </code></pre>
   *
   * To properly build @Anno, the IntegerLiteralExpr "1" must be converted from an int to a long.
   */
  private Object convert(Number number, TypeKind expectedKind) {
    return convert(number, expectedKind, false);
  }

  /**
   * Converts {@code number} to {@code expectedKind}. The value converted is multiplied by -1 if
   * {@code negate} is true
   *
   * @param number a Number value to be converted
   * @param expectedKind one of type {byte, short, int, long, char, float, double}
   * @param negate whether to negate the value of the Number Object while converting
   * @return the converted Object
   */
  private Object convert(Number number, TypeKind expectedKind, boolean negate) {
    byte scalefactor = (byte) (negate ? -1 : 1);
    switch (expectedKind) {
      case BYTE:
        return number.byteValue() * scalefactor;
      case SHORT:
        return number.shortValue() * scalefactor;
      case INT:
        return number.intValue() * scalefactor;
      case LONG:
        return number.longValue() * scalefactor;
      case CHAR:
        // It's not possible for `number` to be negative when `expectedkind` is a CHAR, and
        // casting a negative value to char is illegal.
        if (negate) {
          throw new BugInCF(
              "convert(%s, %s, %s): can't negate a char", number, expectedKind, negate);
        }
        return (char) number.intValue();
      case FLOAT:
        return number.floatValue() * scalefactor;
      case DOUBLE:
        return number.doubleValue() * scalefactor;
      default:
        throw new BugInCF("Unexpected expectedKind: " + expectedKind);
    }
  }

  /**
   * Adds an annotation element (argument) to {@code builder}. The element is a Java expression.
   *
   * @param builder the builder to side-effect
   * @param name the element name
   * @param expr the element value
   * @throws AnnotationFileParserException if the expression cannot be parsed and added to {@code
   *     builder}
   */
  private void builderAddElement(AnnotationBuilder builder, String name, Expression expr)
      throws AnnotationFileParserException {
    ExecutableElement var = builder.findElement(name);
    TypeMirror declaredType = var.getReturnType();
    TypeKind valueKind;
    if (declaredType.getKind() == TypeKind.ARRAY) {
      valueKind = ((ArrayType) declaredType).getComponentType().getKind();
    } else {
      valueKind = declaredType.getKind();
    }
    if (expr instanceof ArrayInitializerExpr) {
      if (declaredType.getKind() != TypeKind.ARRAY) {
        throw new AnnotationFileParserException(
            "unhandled annotation attribute type: " + expr + " and declaredType: " + declaredType);
      }

      List<Expression> arrayExpressions = ((ArrayInitializerExpr) expr).getValues();
      Object[] values = new Object[arrayExpressions.size()];

      for (int i = 0; i < arrayExpressions.size(); ++i) {
        Expression eltExpr = arrayExpressions.get(i);
        values[i] = getValueOfExpressionInAnnotation(name, eltExpr, valueKind);
      }
      builder.setValue(name, values);
    } else {
      Object value = getValueOfExpressionInAnnotation(name, expr, valueKind);
      if (declaredType.getKind() == TypeKind.ARRAY) {
        Object[] valueArray = {value};
        builder.setValue(name, valueArray);
      } else {
        builderSetValue(builder, name, value);
      }
    }
  }

  /**
   * Cast to non-array values so that correct the correct AnnotationBuilder#setValue method is
   * called. (Different types of values are handled differently.)
   *
   * @param builder the builder to side-effect
   * @param name the element name
   * @param value the element value
   */
  private void builderSetValue(AnnotationBuilder builder, String name, Object value) {
    if (value instanceof Boolean) {
      builder.setValue(name, (Boolean) value);
    } else if (value instanceof Character) {
      builder.setValue(name, (Character) value);
    } else if (value instanceof Class<?>) {
      builder.setValue(name, (Class<?>) value);
    } else if (value instanceof Double) {
      builder.setValue(name, (Double) value);
    } else if (value instanceof Enum<?>) {
      builder.setValue(name, (Enum<?>) value);
    } else if (value instanceof Float) {
      builder.setValue(name, (Float) value);
    } else if (value instanceof Integer) {
      builder.setValue(name, (Integer) value);
    } else if (value instanceof Long) {
      builder.setValue(name, (Long) value);
    } else if (value instanceof Short) {
      builder.setValue(name, (Short) value);
    } else if (value instanceof String) {
      builder.setValue(name, (String) value);
    } else if (value instanceof TypeMirror) {
      builder.setValue(name, (TypeMirror) value);
    } else if (value instanceof VariableElement) {
      builder.setValue(name, (VariableElement) value);
    } else {
      throw new BugInCF("Unexpected builder value: %s", value);
    }
  }

  /**
   * Mapping of a name access expression that has already been encountered to the resolved variable
   * element.
   */
  private final Map<NameExpr, VariableElement> findVariableElementNameCache = new HashMap<>();

  /**
   * Returns the element for the given variable.
   *
   * @param nexpr the variable name
   * @return the element for the given variable
   */
  private @Nullable VariableElement findVariableElement(NameExpr nexpr) {
    if (findVariableElementNameCache.containsKey(nexpr)) {
      return findVariableElementNameCache.get(nexpr);
    }

    VariableElement res = null;
    boolean importFound = false;
    for (String imp : importedConstants) {
      Pair<@FullyQualifiedName String, String> partitionedName =
          AnnotationFileUtil.partitionQualifiedName(imp);
      String typeName = partitionedName.first;
      String fieldName = partitionedName.second;
      if (fieldName.equals(nexpr.getNameAsString())) {
        TypeElement enclType =
            getTypeElement(
                typeName,
                String.format("Enclosing type of static import %s not found", fieldName),
                nexpr);

        if (enclType == null) {
          return null;
        } else {
          importFound = true;
          res = findFieldElement(enclType, fieldName, nexpr);
          break;
        }
      }
    }

    if (res == null) {
      if (importFound) {
        // TODO: Is this warning redundant?  Maybe imported but invalid types or fields will
        // have warnings from above.
        stubWarnNotFound(nexpr, nexpr.getName() + " was imported but not found");
      } else {
        stubWarnNotFound(nexpr, "Static field " + nexpr.getName() + " is not imported");
      }
    }

    findVariableElementNameCache.put(nexpr, res);
    return res;
  }

  /**
   * Mapping of a field access expression that has already been encountered to the resolved variable
   * element.
   */
  private final Map<FieldAccessExpr, VariableElement> findVariableElementFieldCache =
      new HashMap<>();

  /**
   * Returns the VariableElement for the given field access.
   *
   * @param faexpr a field access expression
   * @return the VariableElement for the given field access
   */
  @SuppressWarnings("signature:argument") // string manipulation
  private @Nullable VariableElement findVariableElement(FieldAccessExpr faexpr) {
    if (findVariableElementFieldCache.containsKey(faexpr)) {
      return findVariableElementFieldCache.get(faexpr);
    }
    TypeElement rcvElt = elements.getTypeElement(faexpr.getScope().toString());
    if (rcvElt == null) {
      // Search importedConstants for full annotation name.
      for (String imp : importedConstants) {
        // TODO: should this use AnnotationFileUtil.partitionQualifiedName?
        String[] importDelimited = imp.split("\\.");
        if (importDelimited[importDelimited.length - 1].equals(faexpr.getScope().toString())) {
          StringBuilder fullAnnotation = new StringBuilder();
          for (int i = 0; i < importDelimited.length - 1; i++) {
            fullAnnotation.append(importDelimited[i]);
            fullAnnotation.append('.');
          }
          fullAnnotation.append(faexpr.getScope().toString());
          rcvElt = elements.getTypeElement(fullAnnotation);
          break;
        }
      }

      if (rcvElt == null) {
        stubWarnNotFound(faexpr, "Type " + faexpr.getScope() + " not found");
        return null;
      }
    }

    VariableElement res = findFieldElement(rcvElt, faexpr.getNameAsString(), faexpr);
    findVariableElementFieldCache.put(faexpr, res);
    return res;
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Map utilities
  ///

  /**
   * Just like Map.put, but does not override any existing value in the map.
   *
   * @param <K> the key type
   * @param <V> the value type
   * @param m a map
   * @param key a key
   * @param value the value to associate with the key, if the key isn't already in the map
   */
  public static <K, V> void putIfAbsent(Map<K, V> m, K key, V value) {
    if (key == null) {
      throw new BugInCF("AnnotationFileParser: key is null for value " + value);
    }
    if (!m.containsKey(key)) {
      m.put(key, value);
    }
  }

  /**
   * If the key is already in the {@code annotationFileAnnos.declAnnos} map, then add the annos to
   * the map value. Otherwise put the key and the annos in the map.
   *
   * @param key a name (actually declaration element string)
   * @param annos the the set of declaration annotations on it, as written in the annotation file
   */
  private void putOrAddToDeclAnnos(String key, Set<AnnotationMirror> annos) {
    Set<AnnotationMirror> stored = annotationFileAnnos.declAnnos.get(key);
    if (stored == null) {
      annotationFileAnnos.declAnnos.put(key, new HashSet<>(annos));
    } else {
      if (fileType != AnnotationFileType.JDK_STUB) {
        stored.addAll(annos);
      } else {
        // JDK annotations should not replace any annotation of the same type.
        List<AnnotationMirror> origStored = new ArrayList<>(stored);
        for (AnnotationMirror anno : annos) {
          if (!AnnotationUtils.containsSameByName(origStored, anno)) {
            stored.add(anno);
          }
        }
      }
    }
  }

  /**
   * Just like Map.put, but modifies an existing annotated type for the given key in {@code m}. If
   * {@code m} already has an annotated type for {@code key}, each annotation in {@code newType}
   * will replace annotations from the same hierarchy at the same location in the existing annotated
   * type. Annotations in other hierarchies will be preserved.
   *
   * @param m the map to put the new type into
   * @param key the key for the map
   * @param newType the new type for the key
   */
  private void putMerge(
      Map<Element, AnnotatedTypeMirror> m, Element key, AnnotatedTypeMirror newType) {
    if (key == null) {
      throw new BugInCF("AnnotationFileParser: key is null");
    }
    if (m.containsKey(key)) {
      AnnotatedTypeMirror existingType = m.get(key);
      // If the newType is from a JDK stub file, then keep the existing type.  This
      // way user-supplied stub files override JDK stub files.
      // This works because the JDK is always parsed last, on demand, after all other stub files.
      if (fileType != AnnotationFileType.JDK_STUB) {
        atypeFactory.replaceAnnotations(newType, existingType);
      }
      m.put(key, existingType);
    } else {
      m.put(key, newType);
    }
  }

  /**
   * Just like Map.putAll, but modifies existing values using {@link #putIfAbsent(Map, Object,
   * Object)}.
   *
   * @param m the destination map
   * @param m2 the source map
   * @param <K> the key type for the maps
   * @param <V> the value type for the maps
   */
  public static <K, V> void putAllNew(Map<K, V> m, Map<K, V> m2) {
    for (Map.Entry<K, V> e2 : m2.entrySet()) {
      putIfAbsent(m, e2.getKey(), e2.getValue());
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Issue warnings
  ///

  /** The warnings that have been issued so far. */
  private static final Set<String> warnings = new HashSet<>();

  /**
   * Issues the given warning about missing elements, only if it has not been previously issued and
   * the -AstubWarnIfNotFound command-line argument was passed.
   *
   * @param astNode where to report errors
   * @param warning warning to print
   */
  private void stubWarnNotFound(NodeWithRange<?> astNode, String warning) {
    stubWarnNotFound(astNode, warning, warnIfNotFound);
  }

  /**
   * Issues the given warning about missing elements, only if it has not been previously issued and
   * the {@code warnIfNotFound} formal parameter is true.
   *
   * @param astNode where to report errors
   * @param warning warning to print
   * @param warnIfNotFound whether to print warnings about types/members that were not found
   */
  private void stubWarnNotFound(NodeWithRange<?> astNode, String warning, boolean warnIfNotFound) {
    if ((fileType.isCommandLine() || warnIfNotFound) || debugAnnotationFileParser) {
      warn(astNode, warning);
    }
  }

  /**
   * Issues the given warning about overwriting bytecode, only if it has not been previously issued
   * and the -AstubWarnIfOverwritesBytecode command-line argument was passed.
   *
   * @param astNode where to report errors
   * @param message the warning message to print
   */
  @SuppressWarnings("UnusedMethod") // not currently used
  private void stubWarnOverwritesBytecode(NodeWithRange<?> astNode, String message) {
    if (warnIfStubOverwritesBytecode || debugAnnotationFileParser) {
      warn(astNode, message);
    }
  }

  /**
   * Issues a warning, only if it has not been previously issued.
   *
   * @param astNode where to report errors
   * @param warning a format string
   * @param args the arguments for {@code warning}
   */
  @FormatMethod
  private void warn(@Nullable NodeWithRange<?> astNode, String warning, Object... args) {
    if (!fileType.isBuiltIn()) {
      warn(astNode, String.format(warning, args));
    }
  }

  /**
   * Issues a warning, only if it has not been previously issued.
   *
   * @param astNode where to report errors
   * @param warning a warning message
   */
  private void warn(@Nullable NodeWithRange<?> astNode, String warning) {
    if (fileType != AnnotationFileType.JDK_STUB) {
      if (warnings.add(warning)) {
        processingEnv
            .getMessager()
            .printMessage(stubWarnDiagnosticKind, fileAndLine(astNode) + warning);
      }
    }
  }

  /**
   * If {@code warning} hasn't been printed yet, and {@code debugAnnotationFileParser} is true,
   * prints the given warning as a diagnostic message.
   *
   * @param warning warning to print
   */
  private void stubDebug(String warning) {
    if (debugAnnotationFileParser && warnings.add(warning)) {
      processingEnv
          .getMessager()
          .printMessage(javax.tools.Diagnostic.Kind.NOTE, "AnnotationFileParser: " + warning);
    }
  }

  /**
   * After obtaining the JavaParser AST for an ajava file and the javac tree for its corresponding
   * Java file, walks both in tandem. For each program construct with annotations, stores the
   * annotations from the ajava file in {@link #annotationFileAnnos} by calling the process method
   * corresponding to that construct, such as {@link #processCallableDeclaration} or {@link
   * #processField}.
   */
  private class AjavaAnnotationCollectorVisitor extends DefaultJointVisitor {
    @Override
    public Void visitClass(ClassTree javacTree, Node javaParserNode) {
      List<AnnotatedTypeVariable> typeDeclTypeParameters = null;
      if (javaParserNode instanceof TypeDeclaration<?>
          && !(javaParserNode instanceof AnnotationDeclaration)) {
        typeDeclTypeParameters =
            processTypeDecl((TypeDeclaration<?>) javaParserNode, null, javacTree);
      }

      super.visitClass(javacTree, javaParserNode);
      if (typeDeclTypeParameters != null) {
        typeParameters.removeAll(typeDeclTypeParameters);
      }

      return null;
    }

    @Override
    public Void visitVariable(VariableTree javacTree, Node javaParserNode) {
      if (TreeUtils.elementFromTree(javacTree) != null) {
        VariableElement elt = TreeUtils.elementFromDeclaration(javacTree);
        if (elt != null) {
          if (elt.getKind() == ElementKind.FIELD) {
            processField((FieldDeclaration) javaParserNode.getParentNode().get(), elt);
          }

          if (elt.getKind() == ElementKind.ENUM_CONSTANT) {
            processEnumConstant((EnumConstantDeclaration) javaParserNode, elt);
          }
        }
      }

      super.visitVariable(javacTree, javaParserNode);
      return null;
    }

    @Override
    public Void visitMethod(MethodTree javacTree, Node javaParserNode) {
      ExecutableElement elt = TreeUtils.elementFromDeclaration(javacTree);
      List<AnnotatedTypeVariable> variablesToClear = null;
      if (javaParserNode instanceof CallableDeclaration<?>) {
        variablesToClear = processCallableDeclaration((CallableDeclaration<?>) javaParserNode, elt);
      }

      super.visitMethod(javacTree, javaParserNode);
      if (variablesToClear != null) {
        typeParameters.removeAll(variablesToClear);
      }

      return null;
    }
  }

  /**
   * Return the prefix for a warning line: A file name, line number, and column number.
   *
   * @param astNode where to report errors
   * @return file name, line number, and column number
   */
  private String fileAndLine(NodeWithRange<?> astNode) {
    String filenamePrinted =
        (processingEnv.getOptions().containsKey("nomsgtext")
            ? new File(filename).getName()
            : filename);

    Optional<Position> begin = astNode == null ? Optional.empty() : astNode.getBegin();
    String lineAndColumn = (begin.isPresent() ? begin.get() + ":" : "");
    return filenamePrinted + ":" + lineAndColumn + " ";
  }

  /** An exception indicating a problem while parsing an annotation file. */
  public static class AnnotationFileParserException extends Exception {

    private static final long serialVersionUID = 20201222;

    /**
     * Create a new AnnotationFileParserException.
     *
     * @param message a description of the problem
     */
    AnnotationFileParserException(String message) {
      super(message);
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Parse state
  ///

  /** Represents a class: its package name and name (including outer class names if any). */
  private static class FqName {
    /** Name of the package being parsed, or null. */
    public @Nullable String packageName;

    /**
     * Name of the type being parsed. Includes outer class names if any. Null if the parser has
     * parsed a package declaration but has not yet gotten to a type declaration.
     */
    public @Nullable String className;

    /**
     * Create a new FqName, which represents a class.
     *
     * @param packageName name of the package, or null
     * @param className unqualified name of the type, including outer class names if any. May be
     *     null.
     */
    public FqName(String packageName, @Nullable String className) {
      this.packageName = packageName;
      this.className = className;
    }

    /** Fully-qualified name of the class. */
    @Override
    @SuppressWarnings("signature") // string concatenation
    public @FullyQualifiedName String toString() {
      if (packageName == null) {
        return className;
      } else {
        return packageName + "." + className;
      }
    }
  }
}
