package org.checkerframework.framework.source;

import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DiagnosticSource;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.Log;
import io.github.classgraph.ClassGraph;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.URI;
import java.time.Instant;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
import java.util.StringJoiner;
import java.util.TreeSet;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.checker.formatter.qual.FormatMethod;
import org.checkerframework.checker.interning.qual.InternedDistinct;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.CanonicalName;
import org.checkerframework.checker.signature.qual.FullyQualifiedName;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.framework.qual.AnnotatedFor;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.util.CheckerMain;
import org.checkerframework.framework.util.OptionConfiguration;
import org.checkerframework.javacutil.AbstractTypeProcessor;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.SystemUtil;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypeSystemError;
import org.checkerframework.javacutil.UserError;
import org.plumelib.util.CollectionsPlume;
import org.plumelib.util.SystemPlume;
import org.plumelib.util.UtilPlume;

/**
 * An abstract annotation processor designed for implementing a source-file checker as an annotation
 * processor (a compiler plug-in). It provides an interface to {@code javac}'s annotation processing
 * API, routines for error reporting via the JSR 199 compiler API, and an implementation for using a
 * {@link SourceVisitor} to perform the type-checking.
 *
 * <p>Most type-checker plug-ins should extend {@link BaseTypeChecker}, instead of this class. Only
 * checkers that require annotated types but not subtype checking (e.g. for testing purposes) should
 * extend this. Non-type checkers (e.g. for enforcing coding styles) may extend {@link
 * AbstractProcessor} (or even this class).
 */
@SupportedOptions({
  // When adding a new standard option:
  // 1. Add a brief blurb here about the use case
  //    and a pointer to one prominent use of the option.
  // 2. Update the Checker Framework manual:
  //     * docs/manual/introduction.tex contains a list of all options,
  //       which should be in the same order as this source code file.
  //     * a specific section should contain a detailed discussion.

  ///
  /// Unsound checking: ignore some errors
  ///

  // A comma-separated list of warnings to suppress
  // org.checkerframework.framework.source.SourceChecker.createSuppressWarnings
  "suppressWarnings",

  // Set inclusion/exclusion of type uses or definitions
  // org.checkerframework.framework.source.SourceChecker.shouldSkipUses and similar
  "skipUses",
  "onlyUses",
  "skipDefs",
  "onlyDefs",

  // Unsoundly assume all methods have no side effects, are deterministic, or both.
  "assumeSideEffectFree",
  "assumeDeterministic",
  "assumePure",

  // Whether to assume that assertions are enabled or disabled
  // org.checkerframework.framework.flow.CFCFGBuilder.CFCFGBuilder
  "assumeAssertionsAreEnabled",
  "assumeAssertionsAreDisabled",

  // Treat checker errors as warnings
  // org.checkerframework.framework.source.SourceChecker.report
  "warns",

  ///
  /// More sound (strict checking): enable errors that are disabled by default
  ///

  // The next ones *increase* rather than *decrease* soundness.  They will eventually be replaced by
  // their complements (except -AconcurrentSemantics) and moved into the above section.

  // TODO: Checking of bodies of @SideEffectFree, @Deterministic, and
  // @Pure methods is temporarily disabled unless -AcheckPurityAnnotations is
  // supplied on the command line.
  // Re-enable it after making the analysis more precise.
  // org.checkerframework.common.basetype.BaseTypeVisitor.visitMethod(MethodTree, Void)
  "checkPurityAnnotations",

  // TODO: Temporary option to make array subtyping invariant,
  // which will be the new default soon.
  "invariantArrays",

  // TODO:  Temporary option to make casts stricter, in particular when
  // casting to an array or generic type. This will be the new default soon.
  "checkCastElementType",

  // Whether to use conservative defaults for bytecode and/or source code.
  // This option takes arguments "source" and/or "bytecode".
  // The default is "-source,-bytecode" (eventually this will be changed to "-source,bytecode").
  // Note, in source code, conservative defaults are never
  // applied to code in the scope of an @AnnotatedFor.
  // See the "Compiling partially-annotated libraries" and
  // "Default qualifiers for \<.class> files (conservative library defaults)"
  // sections in the manual for more details
  // org.checkerframework.framework.source.SourceChecker.useConservativeDefault
  "useConservativeDefaultsForUncheckedCode",
  // Temporary, for backward compatibility
  "useDefaultsForUncheckedCode",

  // Whether to assume sound concurrent semantics or
  // simplified sequential semantics
  // org.checkerframework.framework.flow.CFAbstractTransfer.sequentialSemantics
  "concurrentSemantics",

  // Whether to use a conservative value for type arguments that could not be inferred.
  // See Issue 979.
  "conservativeUninferredTypeArguments",

  // Whether to ignore all subtype tests for type arguments that
  // were inferred for a raw type. Defaults to true.
  // org.checkerframework.framework.type.TypeHierarchy.isSubtypeTypeArguments
  "ignoreRawTypeArguments",

  ///
  /// Type-checking modes:  enable/disable functionality
  ///

  // Lint options
  // org.checkerframework.framework.source.SourceChecker.getSupportedLintOptions() and similar
  "lint",

  // Whether to suggest methods that could be marked @SideEffectFree,
  // @Deterministic, or @Pure
  // org.checkerframework.common.basetype.BaseTypeVisitor.visitMethod(MethodTree, Void)
  "suggestPureMethods",

  // Whether to resolve reflective method invocations.
  // "-AresolveReflection=debug" causes debugging information
  // to be output.
  "resolveReflection",

  // Whether to use whole-program inference. Takes an argument to specify the output format:
  // "-Ainfer=stubs" or "-Ainfer=jaifs".
  "infer",

  // With each warning, in addition to the concrete error key,
  // output the SuppressWarnings strings that can be used to
  // suppress that warning.
  "showSuppressWarningsStrings",

  // Warn about @SuppressWarnings annotations that do not suppress any warnings.
  // org.checkerframework.common.basetype.BaseTypeChecker.warnUnneededSuppressions
  // org.checkerframework.framework.source.SourceChecker.warnUnneededSuppressions
  // org.checkerframework.framework.source.SourceChecker.shouldSuppressWarnings(javax.lang.model.element.Element, java.lang.String)
  // org.checkerframework.framework.source.SourceVisitor.checkForSuppressWarningsAnno
  "warnUnneededSuppressions",

  // Exceptions to -AwarnUnneededSuppressions.
  "warnUnneededSuppressionsExceptions",

  // Require that warning suppression annotations contain a checker key as a prefix in order for
  // the warning to be suppressed.
  // org.checkerframework.framework.source.SourceChecker.checkSuppressWarnings(java.lang.String[],
  // java.lang.String)
  "requirePrefixInWarningSuppressions",

  // Ignore annotations in bytecode that have invalid annotation locations.
  // See https://github.com/typetools/checker-framework/issues/2173
  // org.checkerframework.framework.type.ElementAnnotationApplier.apply
  "ignoreInvalidAnnotationLocations",

  ///
  /// Partially-annotated libraries
  ///

  // Additional stub files to use
  // org.checkerframework.framework.type.AnnotatedTypeFactory.parseStubFiles()
  "stubs",
  // Additional ajava files to use
  // org.checkerframework.framework.type.AnnotatedTypeFactory.parserAjavaFiles()
  "ajava",
  // Whether to print warnings about types/members in a stub file
  // that were not found on the class path
  // org.checkerframework.framework.stub.AnnotationFileParser.warnIfNotFound
  "stubWarnIfNotFound",
  // Whether to ignore missing classes even when warnIfNotFound is set to true and other classes
  // from the same package are present (useful if a package spans more than one jar).
  // org.checkerframework.framework.stub.AnnotationFileParser.warnIfNotFoundIgnoresClasses
  "stubWarnIfNotFoundIgnoresClasses",
  // Whether to print warnings about stub files that overwrite annotations from bytecode.
  "stubWarnIfOverwritesBytecode",
  // Whether to print warnings about stub files that are redundant with the annotations from
  // bytecode.
  "stubWarnIfRedundantWithBytecode",
  // Whether to issue a NOTE rather than a WARNING for -AstubWarn* command-line options
  "stubWarnNote",
  // With this option, annotations in stub files are used EVEN IF THE SOURCE FILE IS
  // PRESENT. Only use this option when you intend to store types in stub files rather than
  // directly in source code, such as during whole-program inference. The annotations in the
  // stub files will be glb'd with those in the source code before local inference begins.
  "mergeStubsWithSource",
  // Already listed above, but worth noting again in this section:
  // "useConservativeDefaultsForUncheckedCode"

  ///
  /// Debugging
  ///

  /// Amount of detail in messages

  // Print the version of the Checker Framework
  "version",
  // Print info about git repository from which the Checker Framework was compiled
  "printGitProperties",

  // Whether to print @InvisibleQualifier marked annotations
  // org.checkerframework.framework.type.AnnotatedTypeMirror.toString()
  "printAllQualifiers",

  // Whether to print [] around a set of type parameters in order to clearly see where they end
  // e.g.  <E extends F, F extends Object>
  // without this option the E is printed: E extends F extends Object
  // with this option:                     E [ extends F [ extends Object super Void ] super Void ]
  // when multiple type variables are used this becomes useful very quickly
  "printVerboseGenerics",

  // Whether to NOT output a stack trace for each framework error.
  // org.checkerframework.framework.source.SourceChecker.logBugInCF
  "noPrintErrorStack",

  // Only output error code, useful for testing framework
  // org.checkerframework.framework.source.SourceChecker.message(Kind, Object, String, Object...)
  "nomsgtext",

  /// Format of messages

  // Output detailed message in simple-to-parse format, useful
  // for tools parsing Checker Framework output.
  // org.checkerframework.framework.source.SourceChecker.message(Kind, Object, String, Object...)
  "detailedmsgtext",

  /// Stub and JDK libraries

  // Ignore the standard jdk.astub file; primarily for testing or debugging.
  // org.checkerframework.framework.type.AnnotatedTypeFactory.parseStubFiles()
  "ignorejdkastub",

  // Whether to check that the annotated JDK is correctly provided
  // org.checkerframework.common.basetype.BaseTypeVisitor.checkForAnnotatedJdk()
  "permitMissingJdk",
  "nocheckjdk", // temporary, for backward compatibility

  // Parse all JDK files at startup rather than as needed.
  // org.checkerframework.framework.stub.AnnotationFileElementTypes.AnnotationFileElementTypes
  "parseAllJdk",

  // Whether to print debugging messages while processing the stub files
  // org.checkerframework.framework.stub.AnnotationFileParser.debugAnnotationFileParser
  "stubDebug",

  /// Progress tracing

  // Output file names before checking
  // org.checkerframework.framework.source.SourceChecker.typeProcess()
  "filenames",

  // Output all subtyping checks
  // org.checkerframework.common.basetype.BaseTypeVisitor
  "showchecks",

  // Output information about intermediate steps in method type argument inference
  // org.checkerframework.framework.util.typeinference.DefaultTypeArgumentInference
  "showInferenceSteps",

  // Output a stack trace when reporting errors or warnings
  // org.checkerframework.common.basetype.SourceChecker.printStackTrace()
  "dumpOnErrors",

  /// Visualizing the CFG

  // Implemented in the wrapper rather than this file, but worth noting here.
  // -AoutputArgsToFile

  // Mechanism to visualize the control flow graph (CFG).
  // The argument is a sequence of values or key-value pairs.
  // The first argument has to be the fully-qualified name of the
  // org.checkerframework.dataflow.cfg.CFGVisualizer implementation that should be used. The
  // remaining values or key-value pairs are passed to CFGVisualizer.init.
  // For example:
  //    -Acfgviz=MyViz,a,b=c,d
  // instantiates class MyViz and calls CFGVisualizer.init
  // with {"a" -> true, "b" -> "c", "d" -> true}.
  "cfgviz",

  // Directory for .dot files generated from the CFG visualization in
  // org.checkerframework.dataflow.cfg.DOTCFGVisualizer
  // as initialized by
  // org.checkerframework.framework.type.GenericAnnotatedTypeFactory.createCFGVisualizer()
  // -Aflowdotdir=xyz
  // is short-hand for
  // -Acfgviz=org.checkerframework.dataflow.cfg.DOTCFGVisualizer,outdir=xyz
  "flowdotdir",

  // Enable additional output in the CFG visualization.
  // -Averbosecfg
  // is short-hand for
  // -Acfgviz=MyClass,verbose
  "verbosecfg",

  /// Caches

  // Set the cache size for caches in AnnotatedTypeFactory
  "atfCacheSize",

  // Sets AnnotatedTypeFactory shouldCache to false
  "atfDoNotCache",

  /// Miscellaneous debugging options

  // Whether to output resource statistics at JVM shutdown
  // org.checkerframework.framework.source.SourceChecker.shutdownHook()
  "resourceStats",

  // Parse all JDK files at startup rather than as needed.
  "parseAllJdk",

  // Run checks that test ajava files.
  //
  // Whenever processing a source file, parse it with JavaParser and check that the AST can be
  // matched with javac's tree. Crash if not. For testing the class JointJavacJavaParserVisitor.
  //
  // Also checks that annotations can be inserted. For each Java file, clears all annotations and
  // reinserts them, then checks if the original and modified ASTs are equivalent.
  "ajavaChecks",
})
public abstract class SourceChecker extends AbstractTypeProcessor implements OptionConfiguration {

  // TODO A checker should export itself through a separate interface, and maybe have an interface
  // for all the methods for which it's safe to override.

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

  /** The message key that will suppress all warnings (it matches any message key). */
  public static final String SUPPRESS_ALL_MESSAGE_KEY = "all";

  /** The SuppressWarnings prefix that will suppress warnings for all checkers. */
  public static final String SUPPRESS_ALL_PREFIX = "allcheckers";

  /** The message key emitted when an unused warning suppression is found. */
  public static final @CompilerMessageKey String UNNEEDED_SUPPRESSION_KEY = "unneeded.suppression";

  /** File name of the localized messages. */
  protected static final String MSGS_FILE = "messages.properties";

  /**
   * Maps error keys to localized/custom error messages. Do not use directly; call {@link
   * #fullMessageOf} or {@link #processArg}.
   */
  protected Properties messagesProperties;

  /** Used to report error messages and warnings via the compiler. */
  protected Messager messager;

  /** Used as a helper for the {@link SourceVisitor}. */
  protected Trees trees;

  /** The source tree that is being scanned. */
  protected @InternedDistinct CompilationUnitTree currentRoot;

  /** The visitor to use. */
  protected SourceVisitor<?, ?> visitor;

  /**
   * Exceptions to -AwarnUnneededSuppressions processing. No warning about unneeded suppressions is
   * issued if the SuppressWarnings string matches this pattern.
   */
  private @Nullable Pattern warnUnneededSuppressionsExceptions;

  /**
   * SuppressWarnings strings supplied via the -AsuppressWarnings option. Do not use directly, call
   * {@link #getSuppressWarningsStringsFromOption()}.
   */
  private String @Nullable [] suppressWarningsStringsFromOption;

  /**
   * If true, use the "allcheckers:" warning string prefix.
   *
   * <p>Checkers that never issue any error messages should set this to false. That prevents {@code
   * -AwarnUnneededSuppressions} from issuing warnings about
   * {@code @SuppressWarnings("allcheckers:...")}.
   */
  protected boolean useAllcheckersPrefix = true;

  /**
   * Regular expression pattern to specify Java classes that are not annotated, so warnings about
   * uses of them should be suppressed.
   *
   * <p>It contains the pattern specified by the user, through the option {@code checkers.skipUses};
   * otherwise it contains a pattern that can match no class.
   */
  private Pattern skipUsesPattern;

  /**
   * Regular expression pattern to specify Java classes that are annotated, so warnings about them
   * should be issued but warnings about all other classes should be suppressed.
   *
   * <p>It contains the pattern specified by the user, through the option {@code checkers.onlyUses};
   * otherwise it contains a pattern that matches every class.
   */
  private Pattern onlyUsesPattern;

  /**
   * Regular expression pattern to specify Java classes whose definition should not be checked.
   *
   * <p>It contains the pattern specified by the user, through the option {@code checkers.skipDefs};
   * otherwise it contains a pattern that can match no class.
   */
  private Pattern skipDefsPattern;

  /**
   * Regular expression pattern to specify Java classes whose definition should be checked.
   *
   * <p>It contains the pattern specified by the user, through the option {@code checkers.onlyDefs};
   * otherwise it contains a pattern that matches every class.
   */
  private Pattern onlyDefsPattern;

  /** The supported lint options. */
  private Set<String> supportedLints;

  /** The enabled lint options. */
  private Set<String> activeLints;

  /**
   * The active options for this checker. This is a processed version of {@link
   * ProcessingEnvironment#getOptions()}: If the option is of the form "-ACheckerName_key=value" and
   * the current checker class, or one of its superclasses, is named "CheckerName", then add key
   * &rarr; value. If the option is of the form "-ACheckerName_key=value" and the current checker
   * class, and none of its superclasses, is named "CheckerName", then do not add key &rarr; value.
   * If the option is of the form "-Akey=value", then add key &rarr; value.
   *
   * <p>Both the simple and the canonical name of the checker can be used. Superclasses of the
   * current checker are also considered.
   */
  private Map<String, String> activeOptions;

  /**
   * The string that separates the checker name from the option name in a "-A" command-line
   * argument. This string may only consist of valid Java identifier part characters, because it
   * will be used within the key of an option.
   */
  protected static final String OPTION_SEPARATOR = "_";

  /**
   * The checker that called this one, whether that be a BaseTypeChecker (used as a compound
   * checker) or an AggregateChecker. Null if this is the checker that calls all others. Note that
   * in the case of a compound checker, the compound checker is the parent, not the checker that was
   * run prior to this one by the compound checker.
   */
  protected @Nullable SourceChecker parentChecker;

  /** List of upstream checker names. Includes the current checker. */
  protected List<@FullyQualifiedName String> upstreamCheckerNames;

  @Override
  public final synchronized void init(ProcessingEnvironment env) {
    ProcessingEnvironment unwrappedEnv = unwrapProcessingEnvironment(env);
    super.init(unwrappedEnv);
    // The processingEnvironment field will be set by the superclass's init method.
    // This is used to trigger AggregateChecker's setProcessingEnvironment.
    setProcessingEnvironment(unwrappedEnv);

    // Keep in sync with check in checker-framework/build.gradle and text in installation
    // section of manual.
    int jreVersion = SystemUtil.getJreVersion();
    if (jreVersion < 8) {
      throw new UserError(
          "Use JDK 8 or JDK 11 to run the Checker Framework.  You are using version %d.",
          jreVersion);
    } else if (jreVersion > 12) {
      throw new UserError(
          String.format(
              "Use JDK 8 or JDK 11 to run the Checker Framework.  You are using version %d.",
              jreVersion));
    } else if (jreVersion != 8 && jreVersion != 11) {
      message(
          Kind.WARNING,
          "Use JDK 8 or JDK 11 to run the Checker Framework.  You are using version %d.",
          jreVersion);
    }

    if (!hasOption("warnUnneededSuppressionsExceptions")) {
      warnUnneededSuppressionsExceptions = null;
    } else {
      String warnUnneededSuppressionsExceptionsString =
          getOption("warnUnneededSuppressionsExceptions");
      if (warnUnneededSuppressionsExceptionsString == null) {
        throw new UserError("Must supply an argument to -AwarnUnneededSuppressionsExceptions");
      }
      try {
        warnUnneededSuppressionsExceptions =
            Pattern.compile(warnUnneededSuppressionsExceptionsString);
      } catch (PatternSyntaxException e) {
        throw new UserError(
            "Argument to -AwarnUnneededSuppressionsExceptions is not a regular expression: "
                + e.getMessage());
      }
    }

    if (hasOption("printGitProperties")) {
      printGitProperties();
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Getters and setters
  ///

  /**
   * Returns the {@link ProcessingEnvironment} that was supplied to this checker.
   *
   * @return the {@link ProcessingEnvironment} that was supplied to this checker
   */
  public ProcessingEnvironment getProcessingEnvironment() {
    return this.processingEnv;
  }

  /** Set the processing environment of the current checker. */
  /* This method is protected only to allow the AggregateChecker and BaseTypeChecker to call it. */
  protected void setProcessingEnvironment(ProcessingEnvironment env) {
    this.processingEnv = env;
  }

  /** Set the parent checker of the current checker. */
  protected void setParentChecker(SourceChecker parentChecker) {
    this.parentChecker = parentChecker;
  }

  /**
   * Returns the immediate parent checker of the current checker.
   *
   * @return the immediate parent checker of the current checker, or null if there is none
   */
  public @Nullable SourceChecker getParentChecker() {
    return this.parentChecker;
  }

  /**
   * Invoked when the current compilation unit root changes.
   *
   * @param newRoot the new compilation unit root
   */
  @SuppressWarnings("interning:assignment") // used in == tests
  protected void setRoot(CompilationUnitTree newRoot) {
    this.currentRoot = newRoot;
    visitor.setRoot(currentRoot);
  }

  /**
   * Returns a list containing this checker name and all checkers it is a part of (that is, checkers
   * that called it).
   *
   * @return a list containing this checker name and all checkers it is a part of (that is, checkers
   *     that called it)
   */
  public List<@FullyQualifiedName String> getUpstreamCheckerNames() {
    if (upstreamCheckerNames == null) {
      upstreamCheckerNames = new ArrayList<>();

      SourceChecker checker = this;

      while (checker != null) {
        upstreamCheckerNames.add(checker.getClass().getCanonicalName());
        checker = checker.parentChecker;
      }
    }

    return upstreamCheckerNames;
  }

  /**
   * Returns the OptionConfiguration associated with this.
   *
   * @return the OptionConfiguration associated with this
   */
  public OptionConfiguration getOptionConfiguration() {
    return this;
  }

  /**
   * Returns the element utilities associated with this.
   *
   * @return the element utilities associated with this
   */
  public Elements getElementUtils() {
    return getProcessingEnvironment().getElementUtils();
  }

  /**
   * Returns the type utilities associated with this.
   *
   * @return the type utilities associated with this
   */
  public Types getTypeUtils() {
    return getProcessingEnvironment().getTypeUtils();
  }

  /**
   * Returns the tree utilities associated with this.
   *
   * @return the tree utilities associated with this
   */
  public Trees getTreeUtils() {
    return Trees.instance(getProcessingEnvironment());
  }

  /**
   * Returns the SourceVisitor associated with this.
   *
   * @return the SourceVisitor associated with this
   */
  public SourceVisitor<?, ?> getVisitor() {
    return this.visitor;
  }

  /**
   * Provides the {@link SourceVisitor} that the checker should use to scan input source trees.
   *
   * @return a {@link SourceVisitor} to use to scan source trees
   */
  protected abstract SourceVisitor<?, ?> createSourceVisitor();

  /**
   * Returns the AnnotationProvider (the type factory) associated with this.
   *
   * @return the AnnotationProvider (the type factory) associated with this
   */
  public AnnotationProvider getAnnotationProvider() {
    throw new UnsupportedOperationException(
        "getAnnotationProvider is not implemented for this class.");
  }

  /**
   * Provides a mapping of error keys to custom error messages.
   *
   * <p>As a default, this implementation builds a {@link Properties} out of file {@code
   * messages.properties}. It accumulates all the properties files in the Java class hierarchy from
   * the checker up to {@code SourceChecker}. This permits subclasses to inherit default messages
   * while being able to override them.
   *
   * @return a {@link Properties} that maps error keys to error message text
   */
  public Properties getMessagesProperties() {
    if (messagesProperties != null) {
      return messagesProperties;
    }

    messagesProperties = new Properties();

    ArrayDeque<Class<?>> checkers = new ArrayDeque<>();
    Class<?> currClass = this.getClass();
    while (currClass != AbstractTypeProcessor.class) {
      checkers.addFirst(currClass);
      currClass = currClass.getSuperclass();
    }

    for (Class<?> checker : checkers) {
      messagesProperties.putAll(getProperties(checker, MSGS_FILE, true));
    }
    return messagesProperties;
  }

  /**
   * Return the given skip pattern if supplied by the user, or else a pattern that matches nothing.
   *
   * @param patternName "skipUses" or "skipDefs"
   * @param options the command-line options
   * @return the user-supplied regex for the given pattern, or a regex that matches nothing
   */
  private Pattern getSkipPattern(String patternName, Map<String, String> options) {
    // Default is an illegal Java identifier substring
    // so that it won't match anything.
    // Note that AnnotatedType's toString output format contains characters such as "():{}".
    return getPattern(patternName, options, "\\]'\"\\]");
  }

  /**
   * Return the given only pattern if supplied by the user, or else a pattern that matches
   * everything.
   *
   * @param patternName "onlyUses" or "onlyDefs"
   * @param options the command-line options
   * @return the user-supplied regex for the given pattern, or a regex that matches everything
   */
  private Pattern getOnlyPattern(String patternName, Map<String, String> options) {
    // default matches everything
    return getPattern(patternName, options, ".");
  }

  private Pattern getPattern(
      String patternName, Map<String, String> options, String defaultPattern) {
    String pattern = "";

    if (options.containsKey(patternName)) {
      pattern = options.get(patternName);
      if (pattern == null) {
        message(
            Kind.WARNING,
            "The " + patternName + " property is empty; please fix your command line");
        pattern = "";
      }
    } else if (System.getProperty("checkers." + patternName) != null) {
      pattern = System.getProperty("checkers." + patternName);
    } else if (System.getenv(patternName) != null) {
      pattern = System.getenv(patternName);
    }

    if (pattern.indexOf("/") != -1) {
      message(
          Kind.WARNING,
          "The "
              + patternName
              + " property contains \"/\", which will never match a class name: "
              + pattern);
    }

    if (pattern.equals("")) {
      pattern = defaultPattern;
    }

    return Pattern.compile(pattern);
  }

  private Pattern getSkipUsesPattern(Map<String, String> options) {
    return getSkipPattern("skipUses", options);
  }

  private Pattern getOnlyUsesPattern(Map<String, String> options) {
    return getOnlyPattern("onlyUses", options);
  }

  private Pattern getSkipDefsPattern(Map<String, String> options) {
    return getSkipPattern("skipDefs", options);
  }

  private Pattern getOnlyDefsPattern(Map<String, String> options) {
    return getOnlyPattern("onlyDefs", options);
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Type-checking
  ///

  /**
   * {@inheritDoc}
   *
   * <p>Type-checkers are not supposed to override this. Instead override initChecker. This allows
   * us to handle BugInCF only here and doesn't require all overriding implementations to be aware
   * of BugInCF.
   *
   * @see AbstractProcessor#init(ProcessingEnvironment)
   * @see SourceChecker#initChecker()
   */
  @Override
  public void typeProcessingStart() {
    try {
      super.typeProcessingStart();
      initChecker();
      if (this.messager == null) {
        messager = processingEnv.getMessager();
        messager.printMessage(
            Kind.WARNING,
            "You have forgotten to call super.initChecker in your "
                + "subclass of SourceChecker, "
                + this.getClass()
                + "! Please ensure your checker is properly initialized.");
      }
      if (shouldAddShutdownHook()) {
        Runtime.getRuntime()
            .addShutdownHook(
                new Thread() {
                  @Override
                  public void run() {
                    shutdownHook();
                  }
                });
      }
      if (hasOption("version")) {
        messager.printMessage(Kind.NOTE, "Checker Framework " + getCheckerVersion());
      }
    } catch (UserError ce) {
      logUserError(ce);
    } catch (TypeSystemError ce) {
      logTypeSystemError(ce);
    } catch (BugInCF ce) {
      logBugInCF(ce);
    } catch (Throwable t) {
      logBugInCF(wrapThrowableAsBugInCF("SourceChecker.typeProcessingStart", t, null));
    }
  }

  /**
   * Initialize the checker.
   *
   * @see AbstractProcessor#init(ProcessingEnvironment)
   */
  public void initChecker() {
    // Grab the Trees and Messager instances now; other utilities
    // (like Types and Elements) can be retrieved by subclasses.
    @Nullable Trees trees = Trees.instance(processingEnv);
    assert trees != null;
    this.trees = trees;

    this.messager = processingEnv.getMessager();
    this.messagesProperties = getMessagesProperties();

    this.visitor = createSourceVisitor();

    // Validate the lint flags, if they haven't been used already.
    if (this.activeLints == null) {
      this.activeLints = createActiveLints(getOptions());
    }
  }

  /** Output the warning about source level at most once. */
  private boolean warnedAboutSourceLevel = false;

  /**
   * If true, javac failed to compile the code or a previously-run annotation processor issued an
   * error.
   */
  protected boolean javacErrored = false;

  /** Output the warning about memory at most once. */
  private boolean warnedAboutGarbageCollection = false;

  /**
   * The number of errors at the last exit of the type processor. At entry to the type processor we
   * check whether the current error count is higher and then don't process the file, as it contains
   * some Java errors. Needs to be protected to allow access from AggregateChecker and
   * BaseTypeChecker.
   */
  protected int errsOnLastExit = 0;

  /**
   * Report "type.checking.not.run" error.
   *
   * @param p error is reported at the leaf of the path
   */
  @SuppressWarnings("interning:assignment") // used in == tests
  protected void reportJavacError(TreePath p) {
    // If javac issued any errors, do not type check any file, so that the Checker Framework
    // does not have to deal with error types.
    currentRoot = p.getCompilationUnit();
    reportError(p.getLeaf(), "type.checking.not.run", getClass().getSimpleName());
  }

  /**
   * Type-check the code using this checker's visitor.
   *
   * @see Processor#process(Set, RoundEnvironment)
   */
  @Override
  public void typeProcess(TypeElement e, TreePath p) {
    if (javacErrored) {
      reportJavacError(p);
      return;
    }

    // Cannot use BugInCF here because it is outside of the try/catch for BugInCF.
    if (e == null) {
      messager.printMessage(Kind.ERROR, "Refusing to process empty TypeElement");
      return;
    }
    if (p == null) {
      messager.printMessage(Kind.ERROR, "Refusing to process empty TreePath in TypeElement: " + e);
      return;
    }
    if (!warnedAboutGarbageCollection && SystemPlume.gcPercentage() > .25) {
      messager.printMessage(
          Kind.WARNING, "Garbage collection consumed over 25% of CPU during the past minute.");
      messager.printMessage(
          Kind.WARNING,
          String.format(
              "Perhaps increase max heap size"
                  + " (max memory = %d, total memory = %d, free memory = %d).",
              Runtime.getRuntime().maxMemory(),
              Runtime.getRuntime().totalMemory(),
              Runtime.getRuntime().freeMemory()));
      warnedAboutGarbageCollection = true;
    }

    Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
    Source source = Source.instance(context);
    // Don't use source.allowTypeAnnotations() because that API changed after 9.
    // Also the enum constant Source.JDK1_8 was renamed at some point...
    if (!warnedAboutSourceLevel && source.compareTo(Source.lookup("8")) < 0) {
      messager.printMessage(
          Kind.WARNING, "-source " + source.name + " does not support type annotations");
      warnedAboutSourceLevel = true;
    }

    Log log = Log.instance(context);
    if (log.nerrors > this.errsOnLastExit) {
      this.errsOnLastExit = log.nerrors;
      javacErrored = true;
      reportJavacError(p);
      return;
    }

    if (visitor == null) {
      // typeProcessingStart invokes initChecker, which should have set the visitor. If the field is
      // still null, an exception occurred during initialization, which was already logged
      // there. Don't also cause a NPE here.
      return;
    }
    if (p.getCompilationUnit() != currentRoot) {
      setRoot(p.getCompilationUnit());
      if (hasOption("filenames")) {
        // TODO: Have a command-line option to turn the timestamps on/off too, because
        // they are nondeterministic across runs.

        // Add timestamp to indicate how long operations are taking.
        // Duplicate messages are suppressed, so this might not appear in front of every "
        // is type-checking " message (when a file takes less than a second to type-check).
        message(Kind.NOTE, Instant.now().toString());
        message(
            Kind.NOTE,
            "%s is type-checking %s",
            (Object) this.getClass().getSimpleName(),
            currentRoot.getSourceFile().getName());
      }
    }

    // Visit the attributed tree.
    try {
      visitor.visit(p);
      warnUnneededSuppressions();
    } catch (UserError ce) {
      logUserError(ce);
    } catch (TypeSystemError ce) {
      logTypeSystemError(ce);
    } catch (BugInCF ce) {
      logBugInCF(ce);
    } catch (Throwable t) {
      logBugInCF(wrapThrowableAsBugInCF("SourceChecker.typeProcess", t, p));
    } finally {
      // Also add possibly deferred diagnostics, which will get published back in
      // AbstractTypeProcessor.
      this.errsOnLastExit = log.nerrors;
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Reporting type-checking errors; most clients use reportError() or reportWarning()
  ///

  /**
   * Reports an error. By default, prints it to the screen via the compiler's internal messager.
   *
   * @param source the source position information; may be an Element, a Tree, or null
   * @param messageKey the message key
   * @param args arguments for interpolation in the string corresponding to the given message key
   */
  public void reportError(Object source, @CompilerMessageKey String messageKey, Object... args) {
    report(source, Kind.ERROR, messageKey, args);
  }

  /**
   * Reports a warning. By default, prints it to the screen via the compiler's internal messager.
   *
   * @param source the source position information; may be an Element, a Tree, or null
   * @param messageKey the message key
   * @param args arguments for interpolation in the string corresponding to the given message key
   */
  public void reportWarning(Object source, @CompilerMessageKey String messageKey, Object... args) {
    report(source, Kind.MANDATORY_WARNING, messageKey, args);
  }

  /**
   * Reports a diagnostic message. By default, prints it to the screen via the compiler's internal
   * messager.
   *
   * <p>Most clients should use {@link #reportError} or {@link #reportWarning}.
   *
   * @param source the source position information; may be an Element, a Tree, or null
   * @param d the diagnostic message
   */
  public void report(Object source, DiagMessage d) {
    report(source, d.getKind(), d.getMessageKey(), d.getArgs());
  }

  /**
   * Reports a diagnostic message. By default, it prints it to the screen via the compiler's
   * internal messager; however, it might also store it for later output.
   *
   * @param source the source position information; may be an Element, a Tree, or null
   * @param kind the type of message
   * @param messageKey the message key
   * @param args arguments for interpolation in the string corresponding to the given message key
   */
  // Not a format method.  However, messageKey should be either a format string for `args`, or  a
  // property key that maps to a format string for `args`.
  // @FormatMethod
  @SuppressWarnings("formatter:format.string") // arg is a format string or a property key
  private void report(
      Object source,
      javax.tools.Diagnostic.Kind kind,
      @CompilerMessageKey String messageKey,
      Object... args) {
    assert messagesProperties != null : "null messagesProperties";

    if (shouldSuppressWarnings(source, messageKey)) {
      return;
    }

    if (args != null) {
      for (int i = 0; i < args.length; ++i) {
        args[i] = processArg(args[i]);
      }
    }

    if (kind == Kind.NOTE) {
      System.err.println("(NOTE) " + String.format(messageKey, args));
      return;
    }

    final String defaultFormat = "(" + messageKey + ")";
    String fmtString;
    if (this.processingEnv.getOptions() != null /*nnbug*/
        && this.processingEnv.getOptions().containsKey("nomsgtext")) {
      fmtString = defaultFormat;
    } else if (this.processingEnv.getOptions() != null /*nnbug*/
        && this.processingEnv.getOptions().containsKey("detailedmsgtext")) {
      // The -Adetailedmsgtext command-line option was given, so output
      // a stylized error message for easy parsing by a tool.
      fmtString =
          detailedMsgTextPrefix(source, defaultFormat, args)
              + fullMessageOf(messageKey, defaultFormat);
    } else {
      fmtString =
          "["
              + suppressWarningsString(messageKey)
              + "] "
              + fullMessageOf(messageKey, defaultFormat);
    }
    String messageText;
    try {
      messageText = String.format(fmtString, args);
    } catch (Exception e) {
      throw new BugInCF(
          "Invalid format string: \"" + fmtString + "\" args: " + Arrays.toString(args), e);
    }

    if (kind == Kind.ERROR && hasOption("warns")) {
      kind = Kind.MANDATORY_WARNING;
    }

    if (source instanceof Element) {
      messager.printMessage(kind, messageText, (Element) source);
    } else if (source instanceof Tree) {
      printOrStoreMessage(kind, messageText, (Tree) source, currentRoot);
    } else {
      throw new BugInCF("invalid position source, class=" + source.getClass());
    }
  }

  /**
   * Print a non-localized message using the javac messager. This is preferable to using System.out
   * or System.err, but should only be used for exceptional cases that don't happen in correct
   * usage. Localized messages should be raised using {@link #reportError}, {@link #reportWarning},
   * etc.
   *
   * @param kind the kind of message to print
   * @param msg the message text
   * @param args optional arguments to substitute in the message
   * @see SourceChecker#report(Object, DiagMessage)
   */
  @FormatMethod
  public void message(javax.tools.Diagnostic.Kind kind, String msg, Object... args) {
    message(kind, String.format(msg, args));
  }

  /**
   * Print a non-localized message using the javac messager. This is preferable to using System.out
   * or System.err, but should only be used for exceptional cases that don't happen in correct
   * usage. Localized messages should be raised using {@link #reportError}, {@link #reportWarning},
   * etc.
   *
   * @param kind the kind of message to print
   * @param msg the message text
   * @see SourceChecker#report(Object, DiagMessage)
   */
  public void message(javax.tools.Diagnostic.Kind kind, String msg) {
    if (messager == null) {
      // If this method is called before initChecker() sets the field
      messager = processingEnv.getMessager();
    }
    messager.printMessage(kind, msg);
  }

  /**
   * Print the given message.
   *
   * @param msg the message to print x
   */
  private void printMessage(String msg) {
    if (messager == null) {
      // If this method is called before initChecker() sets the field
      messager = processingEnv.getMessager();
    }
    messager.printMessage(Kind.ERROR, msg);
  }

  /**
   * Do not call this method. Call {@link #reportError} or {@link #reportWarning} instead.
   *
   * <p>This method exists so that the BaseTypeChecker can override it. For compound checkers, it
   * stores all messages and sorts them by location before outputting them.
   *
   * @param kind the kind of message to print
   * @param message the message text
   * @param source the source code position of the diagnostic message
   * @param root the compilation unit
   */
  protected void printOrStoreMessage(
      javax.tools.Diagnostic.Kind kind, String message, Tree source, CompilationUnitTree root) {
    StackTraceElement[] trace = Thread.currentThread().getStackTrace();
    printOrStoreMessage(kind, message, source, root, trace);
  }

  /**
   * Do not call this method. Call {@link #reportError} or {@link #reportWarning} instead.
   *
   * <p>This method exists so that the BaseTypeChecker can override it. For compound checkers, it
   * stores all messages and sorts them by location before outputting them.
   *
   * @param kind the kind of message to print
   * @param message the message text
   * @param source the source code position of the diagnostic message
   * @param root the compilation unit
   * @param trace the stack trace where the checker encountered an error. It is printed when the
   *     dumpOnErrors option is enabled.
   */
  protected void printOrStoreMessage(
      javax.tools.Diagnostic.Kind kind,
      String message,
      Tree source,
      CompilationUnitTree root,
      StackTraceElement[] trace) {
    Trees.instance(processingEnv).printMessage(kind, message, source, root);
    printStackTrace(trace);
  }

  /**
   * Output the given stack trace if the "dumpOnErrors" option is enabled.
   *
   * @param trace stack trace when the checker encountered a warning/error
   */
  private void printStackTrace(StackTraceElement[] trace) {
    if (hasOption("dumpOnErrors")) {
      StringBuilder msg = new StringBuilder();
      for (StackTraceElement elem : trace) {
        msg.append("\tat " + elem + "\n");
      }
      message(Diagnostic.Kind.NOTE, msg.toString());
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Diagnostic message formatting
  ///

  /**
   * Returns the localized long message corresponding to this key. If not found, tries suffixes of
   * this key, stripping off dot-separated prefixes. If still not found, returns {@code
   * defaultValue}.
   *
   * @param messageKey a message key
   * @param defaultValue a default value to use if {@code messageKey} is not a message key
   * @return the localized long message corresponding to this key or a suffix, or {@code
   *     defaultValue}
   */
  protected String fullMessageOf(String messageKey, String defaultValue) {
    String key = messageKey;

    do {
      if (messagesProperties.containsKey(key)) {
        return messagesProperties.getProperty(key);
      }

      int dot = key.indexOf('.');
      if (dot < 0) {
        return defaultValue;
      }
      key = key.substring(dot + 1);
    } while (true);
  }

  /**
   * Process an argument to an error message before it is passed to String.format.
   *
   * <p>This implementation expands the argument if it is exactly a message key.
   *
   * <p>By contrast, {@link #fullMessageOf} processes the message key itself but not the arguments,
   * and tries suffixes.
   *
   * @param arg the argument
   * @return the result after processing
   */
  protected Object processArg(Object arg) {
    // Check to see if the argument itself is a property to be expanded
    if (arg instanceof String) {
      return messagesProperties.getProperty((String) arg, (String) arg);
    } else {
      return arg;
    }
  }

  /** Separates parts of a "detailed message", to permit easier parsing. */
  public static final String DETAILS_SEPARATOR = " $$ ";

  /**
   * Returns all but the message key part of the message format output by -Adetailedmsgtext.
   *
   * @param source the object from which to obtain source position information; may be an Element, a
   *     Tree, or null
   * @param defaultFormat the message key, in parentheses
   * @param args arguments for interpolation in the string corresponding to the given message key
   * @return the first part of the message format output by -Adetailedmsgtext
   */
  private String detailedMsgTextPrefix(Object source, String defaultFormat, Object[] args) {
    StringJoiner sj = new StringJoiner(DETAILS_SEPARATOR);

    // The parts, separated by " $$ " (DETAILS_SEPARATOR), are:

    // (1) error key
    sj.add(defaultFormat);

    // (2) number of additional tokens, and those tokens; this depends on the error message, and an
    // example is the found and expected types
    if (args != null) {
      sj.add(Integer.toString(args.length));
      for (Object arg : args) {
        sj.add(Objects.toString(arg));
      }
    } else {
      // Output 0 for null arguments.
      sj.add(Integer.toString(0));
    }

    // (3) The error position, as starting and ending characters in the source file.
    sj.add(detailedMsgTextPositionString(sourceToTree(source), currentRoot));

    // (4) The human-readable error message will be added by the caller.
    sj.add(""); // Add DETAILS_SEPARATOR at the end.
    return sj.toString();
  }

  /**
   * Returns the most specific warning suppression string for the warning/error being printed. This
   * is {@code msg} prefixed by a checker name (or "allcheckers") and a colon.
   *
   * @param messageKey the simple, checker-specific error message key
   * @return the most specific SuppressWarnings string for the warning/error being printed
   */
  private String suppressWarningsString(String messageKey) {
    Collection<String> prefixes = this.getSuppressWarningsPrefixes();
    prefixes.remove(SUPPRESS_ALL_PREFIX);
    if (hasOption("showSuppressWarningsStrings")) {
      List<String> list = new ArrayList<>(prefixes);
      // Make sure "allcheckers" is at the end of the list.
      if (useAllcheckersPrefix) {
        list.add(SUPPRESS_ALL_PREFIX);
      }
      return list + ":" + messageKey;
    } else if (hasOption("requirePrefixInWarningSuppressions")) {
      // If the warning key must be prefixed with a prefix (a checker name), then add that to
      // the SuppressWarnings string that is printed.
      String defaultPrefix = getDefaultSuppressWarningsPrefix();
      if (prefixes.contains(defaultPrefix)) {
        return defaultPrefix + ":" + messageKey;
      } else {
        String firstKey = prefixes.iterator().next();
        return firstKey + ":" + messageKey;
      }
    } else {
      return messageKey;
    }
  }

  /**
   * Convert a Tree, Element, or null, into a Tree or null.
   *
   * @param source the object from which to obtain source position information; may be an Element, a
   *     Tree, or null
   * @return the tree associated with the given source object, or null if none
   */
  private @Nullable Tree sourceToTree(@Nullable Object source) {
    if (source instanceof Element) {
      return trees.getTree((Element) source);
    } else if (source instanceof Tree) {
      return (Tree) source;
    } else if (source == null) {
      return null;
    } else {
      throw new BugInCF("Unexpected source %s [%s]", source, source.getClass());
    }
  }

  /**
   * For the given tree, compute the source positions for that tree. Return a "tuple"-like string
   * (e.g. "( 1, 200 )" ) that contains the start and end position of the tree in the current
   * compilation unit. Used only by the -Adetailedmsgtext output format.
   *
   * @param tree tree to locate within the current compilation unit
   * @param currentRoot the current compilation unit
   * @return a tuple string representing the range of characters that tree occupies in the source
   *     file, or the empty string if {@code tree} is null
   */
  private String detailedMsgTextPositionString(Tree tree, CompilationUnitTree currentRoot) {
    if (tree == null) {
      return "";
    }

    SourcePositions sourcePositions = trees.getSourcePositions();
    long start = sourcePositions.getStartPosition(currentRoot, tree);
    long end = sourcePositions.getEndPosition(currentRoot, tree);

    return "( " + start + ", " + end + " )";
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Lint options ("-Alint:xxxx" and "-Alint:-xxxx")
  ///

  /**
   * Determine which lint options are artive.
   *
   * @param options the command-line options
   * @return the active lint options
   */
  private Set<String> createActiveLints(Map<String, String> options) {
    if (!options.containsKey("lint")) {
      return Collections.emptySet();
    }

    String lintString = options.get("lint");
    if (lintString == null) {
      return Collections.singleton("all");
    }

    Set<String> activeLint = new HashSet<>();
    for (String s : lintString.split(",")) {
      if (!this.getSupportedLintOptions().contains(s)
          && !(s.charAt(0) == '-' && this.getSupportedLintOptions().contains(s.substring(1)))
          && !s.equals("all")
          && !s.equals("none")) {
        this.messager.printMessage(
            Kind.WARNING,
            "Unsupported lint option: " + s + "; All options: " + this.getSupportedLintOptions());
      }

      activeLint.add(s);
      if (s.equals("none")) {
        activeLint.add("-all");
      }
    }

    return Collections.unmodifiableSet(activeLint);
  }

  /**
   * Determines the value of the lint option with the given name. Just as <a
   * href="https://docs.oracle.com/javase/7/docs/technotes/guides/javac/index.html">javac</a> uses
   * "-Xlint:xxx" to enable and "-Xlint:-xxx" to disable option xxx, annotation-related lint options
   * are enabled with "-Alint:xxx" and disabled with "-Alint:-xxx".
   *
   * @throws IllegalArgumentException if the option name is not recognized via the {@link
   *     SupportedLintOptions} annotation or the {@link SourceChecker#getSupportedLintOptions}
   *     method
   * @param name the name of the lint option to check for
   * @return true if the lint option was given, false if it was not given or was given prepended
   *     with a "-"
   * @see SourceChecker#getLintOption(String, boolean)
   */
  public final boolean getLintOption(String name) {
    return getLintOption(name, false);
  }

  /**
   * Determines the value of the lint option with the given name. Just as <a
   * href="https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html">javac</a> uses
   * "-Xlint:xxx" to enable and "-Xlint:-xxx" to disable option xxx, annotation-related lint options
   * are enabled with "-Alint=xxx" and disabled with "-Alint=-xxx".
   *
   * @throws IllegalArgumentException if the option name is not recognized via the {@link
   *     SupportedLintOptions} annotation or the {@link SourceChecker#getSupportedLintOptions}
   *     method
   * @param name the name of the lint option to check for
   * @param def the default option value, returned if the option was not given
   * @return true if the lint option was given, false if it was given prepended with a "-", or
   *     {@code def} if it was not given at all
   * @see SourceChecker#getLintOption(String)
   * @see SourceChecker#getOption(String)
   */
  public final boolean getLintOption(String name, boolean def) {

    if (!this.getSupportedLintOptions().contains(name)) {
      throw new UserError("Illegal lint option: " + name);
    }

    if (activeLints == null) {
      activeLints = createActiveLints(getOptions());
    }

    if (activeLints.isEmpty()) {
      return def;
    }

    String tofind = name;
    while (tofind != null) {
      if (activeLints.contains(tofind)) {
        return true;
      } else if (activeLints.contains(String.format("-%s", tofind))) {
        return false;
      }

      tofind = parentOfOption(tofind);
    }

    return def;
  }

  /**
   * Set the value of the lint option with the given name. Just as <a
   * href="https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html">javac</a> uses
   * "-Xlint:xxx" to enable and "-Xlint:-xxx" to disable option xxx, annotation-related lint options
   * are enabled with "-Alint=xxx" and disabled with "-Alint=-xxx". This method can be used by
   * subclasses to enforce having certain lint options enabled/disabled.
   *
   * @throws IllegalArgumentException if the option name is not recognized via the {@link
   *     SupportedLintOptions} annotation or the {@link SourceChecker#getSupportedLintOptions}
   *     method
   * @param name the name of the lint option to set
   * @param val the option value
   * @see SourceChecker#getLintOption(String)
   * @see SourceChecker#getLintOption(String,boolean)
   */
  protected final void setLintOption(String name, boolean val) {
    if (!this.getSupportedLintOptions().contains(name)) {
      throw new UserError("Illegal lint option: " + name);
    }

    /* TODO: warn if the option is also provided on the command line(?)
    boolean exists = false;
    if (!activeLints.isEmpty()) {
        String tofind = name;
        while (tofind != null) {
            if (activeLints.contains(tofind) || // direct
                    activeLints.contains(String.format("-%s", tofind)) || // negation
                    activeLints.contains(tofind.substring(1))) { // name was negation
                exists = true;
            }
            tofind = parentOfOption(tofind);
        }
    }

    if (exists) {
        // TODO: Issue warning?
    }
    TODO: assert that name doesn't start with '-'
    */

    Set<String> newlints = new HashSet<>();
    newlints.addAll(activeLints);
    if (val) {
      newlints.add(name);
    } else {
      newlints.add(String.format("-%s", name));
    }
    activeLints = Collections.unmodifiableSet(newlints);
  }

  /**
   * Helper method to find the parent of a lint key. The lint hierarchy level is denoted by a colon
   * ':'. 'all' is the root for all hierarchy.
   *
   * <pre>
   * Example
   *    cast:unsafe &rarr; cast
   *    cast        &rarr; all
   *    all         &rarr; {@code null}
   * </pre>
   *
   * @param name the lint key whose parest to find
   * @return the parent of the lint key
   */
  private String parentOfOption(String name) {
    if (name.equals("all")) {
      return null;
    }
    int colonIndex = name.lastIndexOf(':');
    if (colonIndex != -1) {
      return name.substring(0, colonIndex);
    } else {
      return "all";
    }
  }

  /**
   * Returns the lint options recognized by this checker. Lint options are those which can be
   * checked for via {@link SourceChecker#getLintOption}.
   *
   * @return an unmodifiable {@link Set} of the lint options recognized by this checker
   */
  public Set<String> getSupportedLintOptions() {
    if (supportedLints == null) {
      supportedLints = createSupportedLintOptions();
    }
    return supportedLints;
  }

  /** Compute the set of supported lint options. */
  protected Set<String> createSupportedLintOptions() {
    @Nullable SupportedLintOptions sl = this.getClass().getAnnotation(SupportedLintOptions.class);

    if (sl == null) {
      return Collections.emptySet();
    }

    @Nullable String @Nullable [] slValue = sl.value();
    assert slValue != null;

    @Nullable String[] lintArray = slValue;
    Set<String> lintSet = new HashSet<>(lintArray.length);
    for (String s : lintArray) {
      lintSet.add(s);
    }
    return Collections.unmodifiableSet(lintSet);
  }

  /**
   * Set the supported lint options. Use of this method should be limited to the AggregateChecker,
   * who needs to set the lint options to the union of all subcheckers. Also, e.g. the
   * NullnessSubchecker need to use this method, as one is created by the other.
   *
   * @param newLints the new supported lint options, which replace any existing ones
   */
  protected void setSupportedLintOptions(Set<String> newLints) {
    supportedLints = newLints;
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Regular (non-lint) options ("-Axxxx")
  ///

  /**
   * Determine which options are active.
   *
   * @param options all provided options
   * @return a value for {@link #activeOptions}
   */
  private Map<String, String> createActiveOptions(Map<String, String> options) {
    if (options.isEmpty()) {
      return Collections.emptyMap();
    }

    Map<String, String> activeOpts = new HashMap<>(CollectionsPlume.mapCapacity(options));

    for (Map.Entry<String, String> opt : options.entrySet()) {
      String key = opt.getKey();
      String value = opt.getValue();

      String[] split = key.split(OPTION_SEPARATOR);

      splitlengthswitch:
      switch (split.length) {
        case 1:
          // No separator, option always active.
          activeOpts.put(key, value);
          break;
        case 2:
          Class<?> clazz = this.getClass();

          do {
            if (clazz.getCanonicalName().equals(split[0])
                || clazz.getSimpleName().equals(split[0])) {
              // Valid class-option pair.
              activeOpts.put(split[1], value);
              break splitlengthswitch;
            }

            clazz = clazz.getSuperclass();
          } while (clazz != null
              && !clazz.getName().equals(AbstractTypeProcessor.class.getCanonicalName()));
          // Didn't find a matching class. Option might be for another processor. Add
          // option anyways. javac will warn if no processor supports the option.
          activeOpts.put(key, value);
          break;
        default:
          // Too many separators. Option might be for another processor. Add option
          // anyways. javac will warn if no processor supports the option.
          activeOpts.put(key, value);
      }
    }
    return Collections.unmodifiableMap(activeOpts);
  }

  /**
   * Add additional active options. Use of this method should be limited to the AggregateChecker,
   * who needs to set the active options to the union of all subcheckers.
   *
   * @param moreOpts the active options to add
   */
  protected void addOptions(Map<String, String> moreOpts) {
    Map<String, String> activeOpts = new HashMap<>(getOptions());
    activeOpts.putAll(moreOpts);
    activeOptions = Collections.unmodifiableMap(activeOpts);
  }

  /**
   * Check whether the given option is provided.
   *
   * <p>Note that {@link #getOption(String)} can still return null even if {@code hasOption} returns
   * true: this happens e.g. for {@code -Amyopt}
   *
   * @param name the name of the option to check
   * @return true if the option name was provided, false otherwise
   */
  @Override
  public final boolean hasOption(String name) {
    return getOptions().containsKey(name);
  }

  /**
   * Determines the value of the option with the given name.
   *
   * @param name the name of the option to check
   * @see SourceChecker#getLintOption(String,boolean)
   */
  @Override
  public final String getOption(String name) {
    return getOption(name, null);
  }

  /**
   * Determines the boolean value of the option with the given name. Returns false if the option is
   * not set.
   *
   * @param name the name of the option to check
   * @see SourceChecker#getLintOption(String,boolean)
   */
  @Override
  public final boolean getBooleanOption(String name) {
    return getBooleanOption(name, false);
  }

  /**
   * Determines the boolean value of the option with the given name. Returns the given default value
   * if the option is not set.
   *
   * @param name the name of the option to check
   * @param defaultValue the default value to use if the option is not set
   * @see SourceChecker#getLintOption(String,boolean)
   */
  @Override
  public final boolean getBooleanOption(String name, boolean defaultValue) {
    String value = getOption(name);
    if (value == null) {
      return defaultValue;
    }
    if (value.equals("true")) {
      return true;
    }
    if (value.equals("false")) {
      return false;
    }
    throw new UserError(
        String.format("Value of %s option should be a boolean, but is \"%s\".", name, value));
  }

  /**
   * Return all active options for this checker.
   *
   * @return all active options for this checker
   */
  @Override
  public Map<String, String> getOptions() {
    if (activeOptions == null) {
      activeOptions = createActiveOptions(processingEnv.getOptions());
    }
    return activeOptions;
  }

  /**
   * Determines the value of the lint option with the given name and returns the default value if
   * nothing is specified.
   *
   * @param name the name of the option to check
   * @param defaultValue the default value to use if the option is not set
   * @see SourceChecker#getOption(String)
   * @see SourceChecker#getLintOption(String)
   */
  @Override
  public final String getOption(String name, String defaultValue) {

    if (!this.getSupportedOptions().contains(name)) {
      throw new UserError("Illegal option: " + name);
    }

    if (activeOptions == null) {
      activeOptions = createActiveOptions(processingEnv.getOptions());
    }

    if (activeOptions.isEmpty()) {
      return defaultValue;
    }

    if (activeOptions.containsKey(name)) {
      return activeOptions.get(name);
    } else {
      return defaultValue;
    }
  }

  /**
   * Map the Checker Framework version of {@link SupportedOptions} to the standard annotation
   * provided version {@link javax.annotation.processing.SupportedOptions}.
   */
  @Override
  public Set<String> getSupportedOptions() {
    Set<String> options = new HashSet<>();

    // Support all options provided with the standard {@link
    // javax.annotation.processing.SupportedOptions} annotation.
    options.addAll(super.getSupportedOptions());

    // For the Checker Framework annotation
    // {@link org.checkerframework.framework.source.SupportedOptions}
    // we additionally add
    Class<?> clazz = this.getClass();
    List<Class<?>> clazzPrefixes = new ArrayList<>();

    do {
      clazzPrefixes.add(clazz);

      SupportedOptions so = clazz.getAnnotation(SupportedOptions.class);
      if (so != null) {
        options.addAll(expandCFOptions(clazzPrefixes, so.value()));
      }
      clazz = clazz.getSuperclass();
    } while (clazz != null
        && !clazz.getName().equals(AbstractTypeProcessor.class.getCanonicalName()));

    return Collections.unmodifiableSet(options);
  }

  /**
   * Generate the possible command-line option names by prefixing each class name from {@code
   * classPrefixes} to {@code options}, separated by {@link #OPTION_SEPARATOR}.
   *
   * @param clazzPrefixes the classes to prefix
   * @param options the option names
   * @return the possible combinations that should be supported
   */
  protected Collection<String> expandCFOptions(
      List<? extends Class<?>> clazzPrefixes, String[] options) {
    Set<String> res = new HashSet<>();

    for (String option : options) {
      res.add(option);
      for (Class<?> clazz : clazzPrefixes) {
        res.add(clazz.getCanonicalName() + OPTION_SEPARATOR + option);
        res.add(clazz.getSimpleName() + OPTION_SEPARATOR + option);
      }
    }
    return res;
  }

  /**
   * Overrides the default implementation to always return a singleton set containing only "*".
   *
   * <p>javac uses this list to determine which classes process; javac only runs an annotation
   * processor on classes that contain at least one of the mentioned annotations. Thus, the effect
   * of returning "*" is as if the checker were annotated by {@code @SupportedAnnotationTypes("*")}:
   * javac runs the checker on every class mentioned on the javac command line. This method also
   * checks that subclasses do not contain a {@link SupportedAnnotationTypes} annotation.
   *
   * <p>To specify the annotations that a checker recognizes as type qualifiers, see {@link
   * AnnotatedTypeFactory#createSupportedTypeQualifiers()}.
   *
   * @throws Error if a subclass is annotated with {@link SupportedAnnotationTypes}
   */
  @Override
  public final Set<String> getSupportedAnnotationTypes() {

    SupportedAnnotationTypes supported =
        this.getClass().getAnnotation(SupportedAnnotationTypes.class);
    if (supported != null) {
      throw new BugInCF(
          "@SupportedAnnotationTypes should not be written on any checker;"
              + " supported annotation types are inherited from SourceChecker.");
    }
    return Collections.singleton("*");
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Warning suppression and unneeded warnings
  ///

  /**
   * Returns the argument to -AsuppressWarnings, split on commas, or null if no such argument. Only
   * ever called once; the value is cached in field {@link #suppressWarningsStringsFromOption}.
   *
   * @return the argument to -AsuppressWarnings, split on commas, or null if no such argument
   */
  private String @Nullable [] getSuppressWarningsStringsFromOption() {
    Map<String, String> options = getOptions();
    if (this.suppressWarningsStringsFromOption == null) {
      if (!options.containsKey("suppressWarnings")) {
        return null;
      }

      String swStrings = options.get("suppressWarnings");
      if (swStrings == null) {
        return null;
      }
      this.suppressWarningsStringsFromOption = swStrings.split(",");
    }

    return this.suppressWarningsStringsFromOption;
  }

  /**
   * Issues a warning about any {@code @SuppressWarnings} that didn't suppress a warning, but starts
   * with this checker name or "allcheckers".
   */
  protected void warnUnneededSuppressions() {
    if (!hasOption("warnUnneededSuppressions")) {
      return;
    }

    Set<Element> elementsSuppress = new HashSet<>(this.elementsWithSuppressedWarnings);
    this.elementsWithSuppressedWarnings.clear();
    Set<String> prefixes = new HashSet<>(getSuppressWarningsPrefixes());
    Set<String> errorKeys = new HashSet<>(messagesProperties.stringPropertyNames());
    warnUnneededSuppressions(elementsSuppress, prefixes, errorKeys);
    getVisitor().treesWithSuppressWarnings.clear();
  }

  /**
   * Issues a warning about any {@code @SuppressWarnings} string that didn't suppress a warning, but
   * starts with one of the given prefixes (checker names).
   *
   * @param elementsSuppress elements with a {@code @SuppressWarnings} that actually suppressed a
   *     warning
   * @param prefixes the SuppressWarnings prefixes that suppress all warnings from this checker
   * @param allErrorKeys all error keys that can be issued by this checker
   */
  protected void warnUnneededSuppressions(
      Set<Element> elementsSuppress, Set<String> prefixes, Set<String> allErrorKeys) {
    for (Tree tree : getVisitor().treesWithSuppressWarnings) {
      Element elt = TreeUtils.elementFromTree(tree);
      // TODO: This test is too coarse.  The fact that this @SuppressWarnings suppressed
      // *some* warning doesn't mean that every value in it did so.
      if (elementsSuppress.contains(elt)) {
        continue;
      }
      // tree has a @SuppressWarnings annotation that didn't suppress any warnings.
      SuppressWarnings suppressAnno = elt.getAnnotation(SuppressWarnings.class);
      String[] suppressWarningsStrings = suppressAnno.value();
      for (String suppressWarningsString : suppressWarningsStrings) {
        if (warnUnneededSuppressionsExceptions != null
            && warnUnneededSuppressionsExceptions.matcher(suppressWarningsString).find(0)) {
          continue;
        }
        for (String prefix : prefixes) {
          if (suppressWarningsString.equals(prefix)
              || suppressWarningsString.startsWith(prefix + ":")) {
            reportUnneededSuppression(tree, suppressWarningsString);
            break; // Don't report the same warning string more than once.
          }
        }
      }
    }
  }

  /**
   * Issues a warning that the string in a {@code @SuppressWarnings} on {@code tree} isn't needed.
   *
   * @param tree has unneeded {@code @SuppressWarnings}
   * @param suppressWarningsString the SuppressWarnings string that isn't needed
   */
  private void reportUnneededSuppression(Tree tree, String suppressWarningsString) {
    Tree swTree = findSuppressWarningsTree(tree);
    report(
        swTree,
        Kind.MANDATORY_WARNING,
        SourceChecker.UNNEEDED_SUPPRESSION_KEY,
        "\"" + suppressWarningsString + "\"",
        getClass().getSimpleName());
  }

  /** The name of the @SuppressWarnings annotation. */
  private final @CanonicalName String suppressWarningsClassName =
      SuppressWarnings.class.getCanonicalName();
  /**
   * Finds the tree that is a {@code @SuppressWarnings} annotation.
   *
   * @param tree a class, method, or variable tree annotated with {@code @SuppressWarnings}
   * @return tree for {@code @SuppressWarnings} or {@code default} if one isn't found
   */
  private Tree findSuppressWarningsTree(Tree tree) {
    List<? extends AnnotationTree> annotations;
    if (TreeUtils.isClassTree(tree)) {
      annotations = ((ClassTree) tree).getModifiers().getAnnotations();
    } else if (tree.getKind() == Tree.Kind.METHOD) {
      annotations = ((MethodTree) tree).getModifiers().getAnnotations();
    } else {
      annotations = ((VariableTree) tree).getModifiers().getAnnotations();
    }

    for (AnnotationTree annotationTree : annotations) {
      if (AnnotationUtils.areSameByName(
          TreeUtils.annotationFromAnnotationTree(annotationTree), suppressWarningsClassName)) {
        return annotationTree;
      }
    }
    throw new BugInCF("Did not find @SuppressWarnings: " + tree);
  }

  /**
   * Returns true if all the warnings pertaining to the given source should be suppressed. This
   * implementation just that delegates to an overloaded, more specific version of {@code
   * shouldSuppressWarnings()}.
   *
   * @param src the position object to test; may be an Element, a Tree, or null
   * @param errKey the error key the checker is emitting
   * @return true if all warnings pertaining to the given source should be suppressed
   * @see #shouldSuppressWarnings(Element, String)
   * @see #shouldSuppressWarnings(Tree, String)
   */
  private boolean shouldSuppressWarnings(@Nullable Object src, String errKey) {
    if (src instanceof Element) {
      return shouldSuppressWarnings((Element) src, errKey);
    } else if (src instanceof Tree) {
      return shouldSuppressWarnings((Tree) src, errKey);
    } else if (src == null) {
      return false;
    } else {
      throw new BugInCF("Unexpected source " + src);
    }
  }

  /**
   * Determines whether all the warnings pertaining to a given tree should be suppressed. Returns
   * true if the tree is within the scope of a @SuppressWarnings annotation, one of whose values
   * suppresses the checker's warnings. Also, returns true if the {@code errKey} matches a string in
   * {@code -AsuppressWarnings}.
   *
   * @param tree the tree that might be a source of a warning
   * @param errKey the error key the checker is emitting
   * @return true if no warning should be emitted for the given tree because it is contained by a
   *     declaration with an appropriately-valued {@literal @}SuppressWarnings annotation; false
   *     otherwise
   */
  public boolean shouldSuppressWarnings(Tree tree, String errKey) {

    Collection<String> prefixes = getSuppressWarningsPrefixes();
    if (prefixes.isEmpty() || (prefixes.contains(SUPPRESS_ALL_PREFIX) && prefixes.size() == 1)) {
      throw new BugInCF(
          "Checker must provide a SuppressWarnings prefix."
              + " SourceChecker#getSuppressWarningsPrefixes was not overridden correctly.");
    }
    if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) {
      return true;
    }

    if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) {
      // If the error key matches a warning string in the -AsuppressWarnings, then suppress
      // the warning.
      return true;
    }

    // trees.getPath might be slow, but this is only used in error reporting
    @Nullable TreePath path = trees.getPath(this.currentRoot, tree);

    @Nullable VariableTree var = TreePathUtil.enclosingVariable(path);
    if (var != null && shouldSuppressWarnings(TreeUtils.elementFromTree(var), errKey)) {
      return true;
    }

    @Nullable MethodTree method = TreePathUtil.enclosingMethod(path);
    if (method != null) {
      @Nullable Element elt = TreeUtils.elementFromTree(method);

      if (shouldSuppressWarnings(elt, errKey)) {
        return true;
      }

      if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
        // Return false immediately. Do NOT check for AnnotatedFor in the enclosing elements,
        // because they may not have an @AnnotatedFor.
        return false;
      }
    }

    @Nullable ClassTree cls = TreePathUtil.enclosingClass(path);
    if (cls != null) {
      @Nullable Element elt = TreeUtils.elementFromTree(cls);

      if (shouldSuppressWarnings(elt, errKey)) {
        return true;
      }

      if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
        // Return false immediately. Do NOT check for AnnotatedFor in the enclosing elements,
        // because they may not have an @AnnotatedFor.
        return false;
      }
    }

    if (useConservativeDefault("source")) {
      // If we got this far without hitting an @AnnotatedFor and returning
      // false, we DO suppress the warning.
      return true;
    }

    return false;
  }

  /**
   * Should conservative defaults be used for the kind of unchecked code indicated by the parameter?
   *
   * @param kindOfCode source or bytecode
   * @return whether conservative defaults should be used
   */
  public boolean useConservativeDefault(String kindOfCode) {
    final boolean useUncheckedDefaultsForSource = false;
    final boolean useUncheckedDefaultsForByteCode = false;
    String option = this.getOption("useConservativeDefaultsForUncheckedCode");
    // Temporary, for backward compatibility.
    if (option == null) {
      this.getOption("useDefaultsForUncheckedCode");
    }

    String[] args = option != null ? option.split(",") : new String[0];
    for (String arg : args) {
      boolean value = arg.indexOf("-") != 0;
      arg = value ? arg : arg.substring(1);
      if (arg.equals(kindOfCode)) {
        return value;
      }
    }
    if (kindOfCode.equals("source")) {
      return useUncheckedDefaultsForSource;
    } else if (kindOfCode.equals("bytecode")) {
      return useUncheckedDefaultsForByteCode;
    } else {
      throw new UserError(
          "SourceChecker: unexpected argument to useConservativeDefault: " + kindOfCode);
    }
  }

  /**
   * Elements with a {@code @SuppressWarnings} that actually suppressed a warning for this checker.
   */
  protected final Set<Element> elementsWithSuppressedWarnings = new HashSet<>();

  /**
   * Determines whether all the warnings pertaining to a given element should be suppressed. Returns
   * true if the element is within the scope of a @SuppressWarnings annotation, one of whose values
   * suppresses all the checker's warnings.
   *
   * @param elt the Element that might be a source of, or related to, a warning
   * @param errKey the error key the checker is emitting
   * @return true if no warning should be emitted for the given Element because it is contained by a
   *     declaration with an appropriately-valued {@code @SuppressWarnings} annotation; false
   *     otherwise
   */
  public boolean shouldSuppressWarnings(@Nullable Element elt, String errKey) {
    if (UNNEEDED_SUPPRESSION_KEY.equals(errKey)) {
      // Never suppress an "unneeded.suppression" warning.
      // TODO: This choice is questionable, because these warnings should be suppressable just
      // like any others.  The reason for the choice is that if a user writes
      // `@SuppressWarnings("nullness")` that isn't needed, then that annotation would
      // suppress the unneeded suppression warning.  It would take extra work to permit more
      // desirable behavior in that case.
      return false;
    }

    if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) {
      return true;
    }

    while (elt != null) {
      SuppressWarnings suppressWarningsAnno = elt.getAnnotation(SuppressWarnings.class);
      if (suppressWarningsAnno != null) {
        String[] suppressWarningsStrings = suppressWarningsAnno.value();
        if (shouldSuppress(suppressWarningsStrings, errKey)) {
          if (hasOption("warnUnneededSuppressions")) {
            elementsWithSuppressedWarnings.add(elt);
          }
          return true;
        }
      }
      if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
        // Return false immediately. Do NOT check for AnnotatedFor in the
        // enclosing elements, because they may not have an @AnnotatedFor.
        return false;
      }
      elt = elt.getEnclosingElement();
    }
    return false;
  }

  /**
   * Determines whether an error (whose message key is {@code messageKey}) should be suppressed. It
   * is suppressed if any of the given SuppressWarnings strings suppresses it.
   *
   * <p>A SuppressWarnings string may be of the following pattern:
   *
   * <ol>
   *   <li>{@code "prefix"}, where prefix is a SuppressWarnings prefix, as specified by {@link
   *       #getSuppressWarningsPrefixes()}. For example, {@code "nullness"} and {@code
   *       "initialization"} for the Nullness Checker, {@code "regex"} for the Regex Checker.
   *   <li>{@code "partial-message-key"}, where partial-message-key is a prefix or suffix of the
   *       message key that it may suppress. So "generic.argument" would suppress any errors whose
   *       message key contains "generic.argument".
   *   <li>{@code "prefix:partial-message-key}, where the prefix and partial-message-key is as
   *       above. So "nullness:generic.argument", would suppress any errors in the Nullness Checker
   *       with a message key that contains "generic.argument".
   * </ol>
   *
   * {@code "allcheckers"} is a prefix that suppresses a warning from any checker. {@code "all"} is
   * a partial-message-key that suppresses a warning with any message key.
   *
   * <p>If the {@code -ArequirePrefixInWarningSuppressions} command-line argument was supplied, then
   * {@code "partial-message-key"} has no effect; {@code "prefix"} and {@code
   * "prefix:partial-message-key"} are the only SuppressWarnings strings that have an effect.
   *
   * @param suppressWarningsStrings the SuppressWarnings strings that are in effect. May be null, in
   *     which case this method returns false.
   * @param messageKey the message key of the error the checker is emitting; a lowercase string,
   *     without any "checkername:" prefix
   * @return true if an element of {@code suppressWarningsStrings} suppresses the error
   */
  private boolean shouldSuppress(String[] suppressWarningsStrings, String messageKey) {
    Set<String> prefixes = this.getSuppressWarningsPrefixes();
    return shouldSuppress(prefixes, suppressWarningsStrings, messageKey);
  }

  /**
   * Helper method for {@link #shouldSuppress(String[], String)}.
   *
   * @param prefixes the SuppressWarnings prefixes used by this checker
   * @param suppressWarningsStrings the SuppressWarnings strings that are in effect. May be null, in
   *     which case this method returns false.
   * @param messageKey the message key of the error the checker is emitting; a lowercase string,
   *     without any "checkername:" prefix
   * @return true if one of the {@code suppressWarningsStrings} suppresses the error
   */
  private boolean shouldSuppress(
      Set<String> prefixes, String[] suppressWarningsStrings, String messageKey) {
    if (suppressWarningsStrings == null) {
      return false;
    }
    // Is the name of the checker required to suppress a warning?
    boolean requirePrefix = hasOption("requirePrefixInWarningSuppressions");

    for (String suppressWarningsString : suppressWarningsStrings) {
      int colonPos = suppressWarningsString.indexOf(":");
      String messageKeyInSuppressWarningsString;
      if (colonPos == -1) {
        // The SuppressWarnings string is not of the form prefix:partial-message-key
        if (prefixes.contains(suppressWarningsString)) {
          // The value in the @SuppressWarnings is exactly a prefix. Suppress the warning
          // no matter its message key.
          return true;
        } else if (requirePrefix) {
          // A prefix is required, but this SuppressWarnings string does not have a
          // prefix; check the next SuppressWarnings string.
          continue;
        } else if (suppressWarningsString.equals(SUPPRESS_ALL_MESSAGE_KEY)) {
          // Prefixes aren't required and the SuppressWarnings string is "all".  Suppress
          // the warning no matter its message key.
          return true;
        }
        // The suppressWarningsString is not a prefix or a prefix:message-key, so it might
        // be a message key.
        messageKeyInSuppressWarningsString = suppressWarningsString;
      } else {
        // The SuppressWarnings string has a prefix.
        String suppressWarningsPrefix = suppressWarningsString.substring(0, colonPos);
        if (!prefixes.contains(suppressWarningsPrefix)) {
          // The prefix of this SuppressWarnings string is a not a prefix supported by
          // this checker. Proceed to the next SuppressWarnings string.
          continue;
        }
        messageKeyInSuppressWarningsString = suppressWarningsString.substring(colonPos + 1);
      }
      // Check if the message key in the warning suppression is part of the message key that
      // the checker is emiting.
      if (messageKey.equals(messageKeyInSuppressWarningsString)
          || messageKey.startsWith(messageKeyInSuppressWarningsString + ".")
          || messageKey.endsWith("." + messageKeyInSuppressWarningsString)
          || messageKey.contains("." + messageKeyInSuppressWarningsString + ".")) {
        return true;
      }
    }

    // None of the SuppressWarnings strings suppress this error.
    return false;
  }

  /**
   * Return true if the element has an {@code @AnnotatedFor} annotation, for this checker or an
   * upstream checker that called this one.
   *
   * @param elt the source code element to check, or null
   * @return true if the element is annotated for this checker or an upstream checker
   */
  private boolean isAnnotatedForThisCheckerOrUpstreamChecker(@Nullable Element elt) {

    if (elt == null || !useConservativeDefault("source")) {
      return false;
    }

    @Nullable AnnotatedFor anno = elt.getAnnotation(AnnotatedFor.class);

    String[] userAnnotatedFors = (anno == null ? null : anno.value());

    if (userAnnotatedFors != null) {
      List<@FullyQualifiedName String> upstreamCheckerNames = getUpstreamCheckerNames();

      for (String userAnnotatedFor : userAnnotatedFors) {
        if (CheckerMain.matchesCheckerOrSubcheckerFromList(
            userAnnotatedFor, upstreamCheckerNames)) {
          return true;
        }
      }
    }

    return false;
  }

  /**
   * Returns a modifiable set of lower-case strings that are prefixes for SuppressWarnings strings.
   *
   * <p>The collection must not be empty and must not contain only {@link #SUPPRESS_ALL_PREFIX}.
   *
   * @return non-empty modifiable set of lower-case prefixes for SuppressWarnings strings
   */
  public SortedSet<String> getSuppressWarningsPrefixes() {
    return getStandardSuppressWarningsPrefixes();
  }

  /**
   * Returns a sorted set of SuppressWarnings prefixes read from the {@link SuppressWarningsPrefix}
   * meta-annotation on the checker class. Or if no {@link SuppressWarningsPrefix} is used, the
   * checker name is used. {@link #SUPPRESS_ALL_PREFIX} is also added, at the end, unless {@link
   * #useAllcheckersPrefix} is false.
   *
   * @return a sorted set of SuppressWarnings prefixes
   */
  protected final NavigableSet<String> getStandardSuppressWarningsPrefixes() {
    NavigableSet<String> prefixes = new TreeSet<>();
    if (useAllcheckersPrefix) {
      prefixes.add(SUPPRESS_ALL_PREFIX);
    }
    SuppressWarningsPrefix prefixMetaAnno =
        this.getClass().getAnnotation(SuppressWarningsPrefix.class);
    if (prefixMetaAnno != null) {
      for (String prefix : prefixMetaAnno.value()) {
        prefixes.add(prefix);
      }
      return prefixes;
    }

    @SuppressWarnings("deprecation") // SuppressWarningsKeys was renamed to SuppressWarningsPrefix
    SuppressWarningsKeys annotation = this.getClass().getAnnotation(SuppressWarningsKeys.class);
    if (annotation != null) {
      for (String prefix : annotation.value()) {
        prefixes.add(prefix);
      }
      return prefixes;
    }

    // No @SuppressWarningsPrefixes annotation, by default infer key from class name.
    String defaultPrefix = getDefaultSuppressWarningsPrefix();
    prefixes.add(defaultPrefix);
    return prefixes;
  }

  /**
   * Returns the default SuppressWarnings prefix for this checker based on the checker name.
   *
   * @return the default SuppressWarnings prefix for this checker based on the checker name
   */
  private String getDefaultSuppressWarningsPrefix() {
    String className = this.getClass().getSimpleName();
    int indexOfChecker = className.lastIndexOf("Checker");
    if (indexOfChecker == -1) {
      indexOfChecker = className.lastIndexOf("Subchecker");
    }
    String result = (indexOfChecker == -1) ? className : className.substring(0, indexOfChecker);
    return result.toLowerCase();
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Skipping uses and defs
  ///

  /**
   * Tests whether the class owner of the passed element is an unannotated class and matches the
   * pattern specified in the {@code checker.skipUses} property.
   *
   * @param element an element
   * @return true iff the enclosing class of element should be skipped
   */
  public final boolean shouldSkipUses(Element element) {
    if (element == null) {
      return false;
    }
    TypeElement typeElement = ElementUtils.enclosingTypeElement(element);
    if (typeElement == null) {
      throw new BugInCF("enclosingTypeElement(%s [%s]) => null%n", element, element.getClass());
    }
    @SuppressWarnings("signature:assignment") // TypeElement.toString(): @FullyQualifiedName
    @FullyQualifiedName String name = typeElement.toString();
    return shouldSkipUses(name);
  }

  /**
   * Tests whether the class owner of the passed type matches the pattern specified in the {@code
   * checker.skipUses} property. In contrast to {@link #shouldSkipUses(Element)} this version can
   * also be used from primitive types, which don't have an element.
   *
   * <p>Checkers that require their annotations not to be checked on certain JDK classes may
   * override this method to skip them. They shall call {@code super.shouldSkipUses(typeName)} to
   * also skip the classes matching the pattern.
   *
   * @param typeName the fully-qualified name of a type
   * @return true iff the enclosing class of element should be skipped
   */
  public boolean shouldSkipUses(@FullyQualifiedName String typeName) {
    // System.out.printf("shouldSkipUses(%s) %s%nskipUses %s%nonlyUses %s%nresult %s%n",
    //                   element,
    //                   name,
    //                   skipUsesPattern.matcher(name).find(),
    //                   onlyUsesPattern.matcher(name).find(),
    //                   (skipUsesPattern.matcher(name).find()
    //                    || ! onlyUsesPattern.matcher(name).find()));
    // StackTraceElement[] stea = new Throwable().getStackTrace();
    // for (int i=0; i<3; i++) {
    //     System.out.println("  " + stea[i]);
    // }
    // System.out.println();
    if (skipUsesPattern == null) {
      skipUsesPattern = getSkipUsesPattern(getOptions());
    }
    if (onlyUsesPattern == null) {
      onlyUsesPattern = getOnlyUsesPattern(getOptions());
    }
    return skipUsesPattern.matcher(typeName).find() || !onlyUsesPattern.matcher(typeName).find();
  }

  /**
   * Tests whether the class definition should not be checked because it matches the {@code
   * checker.skipDefs} property.
   *
   * @param node class to potentially skip
   * @return true if checker should not test node
   */
  public final boolean shouldSkipDefs(ClassTree node) {
    String qualifiedName = TreeUtils.typeOf(node).toString();
    // System.out.printf("shouldSkipDefs(%s) %s%nskipDefs %s%nonlyDefs %s%nresult %s%n%n",
    //                   node,
    //                   qualifiedName,
    //                   skipDefsPattern.matcher(qualifiedName).find(),
    //                   onlyDefsPattern.matcher(qualifiedName).find(),
    //                   (skipDefsPattern.matcher(qualifiedName).find()
    //                    || ! onlyDefsPattern.matcher(qualifiedName).find()));
    if (skipDefsPattern == null) {
      skipDefsPattern = getSkipDefsPattern(getOptions());
    }
    if (onlyDefsPattern == null) {
      onlyDefsPattern = getOnlyDefsPattern(getOptions());
    }

    return skipDefsPattern.matcher(qualifiedName).find()
        || !onlyDefsPattern.matcher(qualifiedName).find();
  }

  /**
   * Tests whether the method definition should not be checked because it matches the {@code
   * checker.skipDefs} property.
   *
   * <p>TODO: currently only uses the class definition. Refine pattern. Same for skipUses.
   *
   * @param cls class to potentially skip
   * @param meth method to potentially skip
   * @return true if checker should not test node
   */
  public final boolean shouldSkipDefs(ClassTree cls, MethodTree meth) {
    return shouldSkipDefs(cls);
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Errors other than type-checking errors
  ///

  /**
   * Log (that is, print) a user error.
   *
   * @param ce the user error to output
   */
  private void logUserError(UserError ce) {
    String msg = ce.getMessage();
    printMessage(msg);
  }

  /**
   * Log (that is, print) a type system error.
   *
   * @param ce the type system error to output
   */
  private void logTypeSystemError(TypeSystemError ce) {
    String msg = ce.getMessage();
    printMessage(msg);
  }

  /**
   * Log (that is, print) an internal error in the framework or a checker.
   *
   * @param ce the internal error to output
   */
  private void logBugInCF(BugInCF ce) {
    StringJoiner msg = new StringJoiner(LINE_SEPARATOR);
    if (ce.getCause() != null && ce.getCause() instanceof OutOfMemoryError) {
      msg.add(
          String.format(
              "OutOfMemoryError (max memory = %d, total memory = %d, free memory = %d)",
              Runtime.getRuntime().maxMemory(),
              Runtime.getRuntime().totalMemory(),
              Runtime.getRuntime().freeMemory()));
    } else {
      msg.add(ce.getMessage());
      boolean noPrintErrorStack =
          (processingEnv != null
              && processingEnv.getOptions() != null
              && processingEnv.getOptions().containsKey("noPrintErrorStack"));

      msg.add("; The Checker Framework crashed.  Please report the crash.");
      if (noPrintErrorStack) {
        msg.add(" To see the full stack trace, don't invoke the compiler with -AnoPrintErrorStack");
      } else {
        if (this.currentRoot != null && this.currentRoot.getSourceFile() != null) {
          msg.add("Compilation unit: " + this.currentRoot.getSourceFile().getName());
        }

        if (this.visitor != null) {
          DiagnosticPosition pos = (DiagnosticPosition) this.visitor.lastVisited;
          if (pos != null) {
            DiagnosticSource source = new DiagnosticSource(this.currentRoot.getSourceFile(), null);
            int linenr = source.getLineNumber(pos.getStartPosition());
            int col = source.getColumnNumber(pos.getStartPosition(), true);
            String line = source.getLine(pos.getStartPosition());

            msg.add("Last visited tree at line " + linenr + " column " + col + ":");
            msg.add(line);
          }
        }
      }
    }

    msg.add("Exception: " + ce.getCause() + "; " + UtilPlume.stackTraceToString(ce.getCause()));
    boolean printClasspath = ce.getCause() instanceof NoClassDefFoundError;
    Throwable cause = ce.getCause().getCause();
    while (cause != null) {
      msg.add("Underlying Exception: " + cause + "; " + UtilPlume.stackTraceToString(cause));
      printClasspath |= cause instanceof NoClassDefFoundError;
      cause = cause.getCause();
    }

    if (printClasspath) {
      msg.add("Classpath:");
      for (URI uri : new ClassGraph().getClasspathURIs()) {
        msg.add(uri.toString());
      }
    }

    printMessage(msg.toString());
  }

  /**
   * Converts a throwable to a BugInCF.
   *
   * @param methodName the method that caught the exception (redundant with stack trace)
   * @param t the throwable to be converted to a BugInCF
   * @param p what source code was being processed
   * @return a BugInCF that wraps the given throwable
   */
  private BugInCF wrapThrowableAsBugInCF(String methodName, Throwable t, @Nullable TreePath p) {
    return new BugInCF(
        methodName
            + ": unexpected Throwable ("
            + t.getClass().getSimpleName()
            + ")"
            + ((p == null)
                ? ""
                : " while processing " + p.getCompilationUnit().getSourceFile().getName())
            + (t.getMessage() == null ? "" : "; message: " + t.getMessage()),
        t);
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Shutdown
  ///

  /**
   * Return true to indicate that method {@link #shutdownHook} should be added as a shutdownHook of
   * the JVM.
   *
   * @return true to add {@link #shutdownHook} as a shutdown hook of the JVM
   */
  protected boolean shouldAddShutdownHook() {
    return hasOption("resourceStats");
  }

  /**
   * Method that gets called exactly once at shutdown time of the JVM. Checkers can override this
   * method to customize the behavior.
   */
  protected void shutdownHook() {
    if (hasOption("resourceStats")) {
      // Check for the "resourceStats" option and don't call shouldAddShutdownHook
      // to allow subclasses to override shouldXXX and shutdownHook and simply
      // call the super implementations.
      printStats();
    }
  }

  /** Print resource usage statistics. */
  protected void printStats() {
    List<MemoryPoolMXBean> memoryPools = ManagementFactory.getMemoryPoolMXBeans();
    for (MemoryPoolMXBean memoryPool : memoryPools) {
      System.out.println("Memory pool " + memoryPool.getName() + " statistics");
      System.out.println("  Pool type: " + memoryPool.getType());
      System.out.println("  Peak usage: " + memoryPool.getPeakUsage());
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Miscellaneous
  ///

  /**
   * A helper function to parse a Properties file.
   *
   * @param cls the class whose location is the base of the file path
   * @param filePath the name/path of the file to be read
   * @param permitNonExisting if true, return an empty Properties if the file does not exist or
   *     cannot be parsed; if false, issue an error
   * @return the properties
   */
  protected Properties getProperties(Class<?> cls, String filePath, boolean permitNonExisting) {
    Properties prop = new Properties();
    try {
      InputStream base = cls.getResourceAsStream(filePath);

      if (base == null) {
        // The property file was not found.
        if (permitNonExisting) {
          return prop;
        } else {
          throw new BugInCF("Couldn't locate properties file " + filePath);
        }
      }

      prop.load(base);
    } catch (IOException e) {
      throw new BugInCF("Couldn't parse properties file: " + filePath, e);
    }
    return prop;
  }

  @Override
  public final SourceVersion getSupportedSourceVersion() {
    return SourceVersion.latest();
  }

  /** True if the git.properties file has been printed. */
  private static boolean gitPropertiesPrinted = false;

  /** Print information about the git repository from which the Checker Framework was compiled. */
  private void printGitProperties() {
    if (gitPropertiesPrinted) {
      return;
    }
    gitPropertiesPrinted = true;

    try (InputStream in = getClass().getResourceAsStream("/git.properties");
        BufferedReader reader = new BufferedReader(new InputStreamReader(in)); ) {
      String line;
      while ((line = reader.readLine()) != null) {
        System.out.println(line);
      }
    } catch (IOException e) {
      System.out.println("IOException while reading git.properties: " + e.getMessage());
    }
  }

  /**
   * Returns the version of the Checker Framework.
   *
   * @return the Checker Framework version
   */
  private String getCheckerVersion() {
    Properties gitProperties = getProperties(getClass(), "/git.properties", false);
    String version = gitProperties.getProperty("git.build.version");
    if (version != null) {
      return version;
    }
    throw new BugInCF("Could not find the version in git.properties");
  }

  /**
   * Gradle and IntelliJ wrap the processing environment to gather information about modifications
   * done by annotation processor during incremental compilation. But the Checker Framework calls
   * methods from javac that require the processing environment to be {@code
   * com.sun.tools.javac.processing.JavacProcessingEnvironment}. They fail if given a proxy. This
   * method unwraps a proxy if one is used.
   *
   * @param env a processing environment
   * @return unwrapped environment if the argument is a proxy created by IntelliJ or Gradle;
   *     original value (the argument) if the argument is a javac processing environment
   * @throws BugInCF if method fails to retrieve {@code
   *     com.sun.tools.javac.processing.JavacProcessingEnvironment}
   */
  private static ProcessingEnvironment unwrapProcessingEnvironment(ProcessingEnvironment env) {
    if (env.getClass().getName()
        == "com.sun.tools.javac.processing.JavacProcessingEnvironment") { // interned
      return env;
    }
    // IntelliJ >2020.3 wraps the processing environment in a dynamic proxy.
    ProcessingEnvironment unwrappedIntelliJ = unwrapIntelliJ(env);
    if (unwrappedIntelliJ != null) {
      return unwrapProcessingEnvironment(unwrappedIntelliJ);
    }
    // Gradle incremental build also wraps the processing environment.
    for (Class<?> envClass = env.getClass();
        envClass != null;
        envClass = envClass.getSuperclass()) {
      ProcessingEnvironment unwrappedGradle = unwrapGradle(envClass, env);
      if (unwrappedGradle != null) {
        return unwrapProcessingEnvironment(unwrappedGradle);
      }
    }
    throw new BugInCF("Unexpected processing environment: %s %s", env, env.getClass());
  }

  /**
   * Tries to unwrap ProcessingEnvironment from proxy in IntelliJ 2020.3 or later.
   *
   * @param env possibly a dynamic proxy wrapping processing environment
   * @return unwrapped processing environment, null if not successful
   */
  private static @Nullable ProcessingEnvironment unwrapIntelliJ(ProcessingEnvironment env) {
    if (!Proxy.isProxyClass(env.getClass())) {
      return null;
    }
    InvocationHandler handler = Proxy.getInvocationHandler(env);
    try {
      Field field = handler.getClass().getDeclaredField("val$delegateTo");
      field.setAccessible(true);
      Object o = field.get(handler);
      if (o instanceof ProcessingEnvironment) {
        return (ProcessingEnvironment) o;
      }
      return null;
    } catch (NoSuchFieldException | IllegalAccessException e) {
      return null;
    }
  }

  /**
   * Tries to unwrap processing environment in Gradle incremental processing. Inspired by project
   * Lombok.
   *
   * @param delegateClass a class in which to find a {@code delegate} field
   * @param env a processing environment wrapper
   * @return unwrapped processing environment, null if not successful
   */
  private static @Nullable ProcessingEnvironment unwrapGradle(
      Class<?> delegateClass, ProcessingEnvironment env) {
    try {
      Field field = delegateClass.getDeclaredField("delegate");
      field.setAccessible(true);
      Object o = field.get(env);
      if (o instanceof ProcessingEnvironment) {
        return (ProcessingEnvironment) o;
      }
      return null;
    } catch (NoSuchFieldException | IllegalAccessException e) {
      return null;
    }
  }

  /**
   * Return the path to the current compilation unit.
   *
   * @return path to the current compilation unit
   */
  public TreePath getPathToCompilationUnit() {
    return TreePath.getPath(currentRoot, currentRoot);
  }
}
