package org.checkerframework.common.basetype;

import com.google.common.collect.ImmutableSet;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
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.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import org.checkerframework.checker.interning.qual.FindDistinct;
import org.checkerframework.checker.interning.qual.InternedDistinct;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.ClassGetName;
import org.checkerframework.common.reflection.MethodValChecker;
import org.checkerframework.dataflow.cfg.visualize.CFGVisualizer;
import org.checkerframework.framework.qual.SubtypeOf;
import org.checkerframework.framework.source.SourceChecker;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.GenericAnnotatedTypeFactory;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.TypeHierarchy;
import org.checkerframework.framework.util.TreePathCacher;
import org.checkerframework.javacutil.AbstractTypeProcessor;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TypeSystemError;
import org.checkerframework.javacutil.UserError;
import org.plumelib.util.CollectionsPlume;
import org.plumelib.util.StringsPlume;

/**
 * An abstract {@link SourceChecker} that provides a simple {@link
 * org.checkerframework.framework.source.SourceVisitor} implementation that type-checks assignments,
 * pseudo-assignments such as parameter passing and method invocation, and method overriding.
 *
 * <p>Most type-checker annotation processor should extend this class, instead of {@link
 * SourceChecker}. Checkers that require annotated types but not subtype checking (e.g. for testing
 * purposes) should extend {@link SourceChecker}. Non-type checkers (e.g. checkers to enforce coding
 * styles) can extend {@link SourceChecker} or {@link AbstractTypeProcessor}; the Checker Framework
 * is not designed for such checkers.
 *
 * <p>It is a convention that, for a type system Foo, the checker, the visitor, and the annotated
 * type factory are named as <i>FooChecker</i>, <i>FooVisitor</i>, and
 * <i>FooAnnotatedTypeFactory</i>. Some factory methods use this convention to construct the
 * appropriate classes reflectively.
 *
 * <p>{@code BaseTypeChecker} encapsulates a group for factories for various representations/classes
 * related the type system, mainly:
 *
 * <ul>
 *   <li>{@link QualifierHierarchy}: to represent the supported qualifiers in addition to their
 *       hierarchy, mainly, subtyping rules
 *   <li>{@link TypeHierarchy}: to check subtyping rules between <b>annotated types</b> rather than
 *       qualifiers
 *   <li>{@link AnnotatedTypeFactory}: to construct qualified types enriched with default qualifiers
 *       according to the type system rules
 *   <li>{@link BaseTypeVisitor}: to visit the compiled Java files and check for violations of the
 *       type system rules
 * </ul>
 *
 * <p>Subclasses must specify the set of type qualifiers they support. See {@link
 * AnnotatedTypeFactory#createSupportedTypeQualifiers()}.
 *
 * <p>If the specified type qualifiers are meta-annotated with {@link SubtypeOf}, this
 * implementation will automatically construct the type qualifier hierarchy. Otherwise, or if this
 * behavior must be overridden, the subclass may override the {@link
 * BaseAnnotatedTypeFactory#createQualifierHierarchy()} method.
 *
 * @checker_framework.manual #creating-compiler-interface The checker class
 */
public abstract class BaseTypeChecker extends SourceChecker {

  @Override
  public void initChecker() {
    // initialize all checkers and share options as necessary
    for (BaseTypeChecker checker : getSubcheckers()) {
      // We need to add all options that are activated for the set of subcheckers to
      // the individual checkers.
      checker.addOptions(super.getOptions());
      // Each checker should "support" all possible lint options - otherwise
      // subchecker A would complain about a lint option for subchecker B.
      checker.setSupportedLintOptions(this.getSupportedLintOptions());

      // initChecker validates the passed options, so call it after setting supported options and
      // lints.
      checker.initChecker();
    }

    if (!getSubcheckers().isEmpty()) {
      messageStore = new TreeSet<>(this::compareCheckerMessages);
    }

    super.initChecker();
  }

  /**
   * The full list of subcheckers that need to be run prior to this one, in the order they need to
   * be run in. This list will only be non-empty for the one checker that runs all other
   * subcheckers. Do not read this field directly. Instead, retrieve it via {@link #getSubcheckers}.
   *
   * <p>If the list still null when {@link #getSubcheckers} is called, then getSubcheckers() will
   * call {@link #instantiateSubcheckers}. However, if the current object was itself instantiated by
   * a prior call to instantiateSubcheckers, this field will have been initialized to an empty list
   * before getSubcheckers() is called, thereby ensuring that this list is non-empty only for one
   * checker.
   */
  private @MonotonicNonNull List<BaseTypeChecker> subcheckers = null;

  /**
   * The list of subcheckers that are direct dependencies of this checker. This list will be
   * non-empty for any checker that has at least one subchecker.
   *
   * <p>Does not need to be initialized to null or an empty list because it is always initialized
   * via calls to instantiateSubcheckers.
   */
  // Set to non-null when subcheckers is.
  private @MonotonicNonNull List<BaseTypeChecker> immediateSubcheckers = null;

  /** Supported options for this checker. */
  private @MonotonicNonNull Set<String> supportedOptions = null;

  /** Options passed to this checker. */
  private @MonotonicNonNull Map<String, String> options = null;

  /**
   * TreePathCacher to share between instances. Initialized either in getTreePathCacher (which is
   * also called from instantiateSubcheckers).
   */
  private TreePathCacher treePathCacher = null;

  /**
   * The list of suppress warnings prefixes supported by this checker or any of its subcheckers
   * (including indirect subcheckers). Do not access this field directly; instead, use {@link
   * #getSuppressWarningsPrefixesOfSubcheckers}.
   */
  private @MonotonicNonNull Collection<String> suppressWarningsPrefixesOfSubcheckers = null;

  @Override
  protected void setRoot(CompilationUnitTree newRoot) {
    super.setRoot(newRoot);
    if (parentChecker == null) {
      // Only clear the path cache if this is the main checker.
      treePathCacher.clear();
    }
  }

  /**
   * Returns the set of subchecker classes on which this checker depends. Returns an empty set if
   * this checker does not depend on any others.
   *
   * <p>Subclasses should override this method to specify subcheckers. If they do so, they should
   * call the super implementation of this method and add dependencies to the returned set so that
   * checkers required for reflection resolution are included if reflection resolution is requested.
   *
   * <p>Each subchecker of this checker may also depend on other checkers. If this checker and one
   * of its subcheckers both depend on a third checker, that checker will only be instantiated once.
   *
   * <p>Though each checker is run on a whole compilation unit before the next checker is run, error
   * and warning messages are collected and sorted based on the location in the source file before
   * being printed. (See {@link #printOrStoreMessage(Diagnostic.Kind, String, Tree,
   * CompilationUnitTree)}.)
   *
   * <p>WARNING: Circular dependencies are not supported nor do checkers verify that their
   * dependencies are not circular. Make sure no circular dependencies are created when overriding
   * this method. (In other words, if checker A depends on checker B, checker B cannot depend on
   * checker A.)
   *
   * <p>This method is protected so it can be overridden, but it should only be called internally by
   * the BaseTypeChecker.
   *
   * <p>The BaseTypeChecker will not modify the list returned by this method, but other clients do
   * modify the list.
   *
   * @return the subchecker classes on which this checker depends
   */
  protected LinkedHashSet<Class<? extends BaseTypeChecker>> getImmediateSubcheckerClasses() {
    if (shouldResolveReflection()) {
      return new LinkedHashSet<>(Collections.singleton(MethodValChecker.class));
    }
    // The returned set will be modified by callees.
    return new LinkedHashSet<>();
  }

  /**
   * Returns whether or not reflection should be resolved.
   *
   * @return true if reflection should be resolved
   */
  public boolean shouldResolveReflection() {
    return hasOptionNoSubcheckers("resolveReflection");
  }

  /**
   * Returns the appropriate visitor that type-checks the compilation unit according to the type
   * system rules.
   *
   * <p>This implementation uses the checker naming convention to create the appropriate visitor. If
   * no visitor is found, it returns an instance of {@link BaseTypeVisitor}. It reflectively invokes
   * the constructor that accepts this checker and the compilation unit tree (in that order) as
   * arguments.
   *
   * <p>Subclasses have to override this method to create the appropriate visitor if they do not
   * follow the checker naming convention.
   *
   * @return the type-checking visitor
   */
  @Override
  protected BaseTypeVisitor<?> createSourceVisitor() {
    // Try to reflectively load the visitor.
    Class<?> checkerClass = this.getClass();

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

    // If a visitor couldn't be loaded reflectively, return the default.
    return new BaseTypeVisitor<BaseAnnotatedTypeFactory>(this);
  }

  /**
   * A public variant of {@link #createSourceVisitor}. Only use this if you know what you are doing.
   *
   * @return the type-checking visitor
   */
  public BaseTypeVisitor<?> createSourceVisitorPublic() {
    return createSourceVisitor();
  }

  /**
   * Returns the name of a class related to a given one, by replacing "Checker" or "Subchecker" by
   * {@code replacement}.
   *
   * @param checkerClass the checker class
   * @param replacement the string to replace "Checker" or "Subchecker" by
   * @return the name of the related class
   */
  @SuppressWarnings("signature") // string manipulation of @ClassGetName string
  public static @ClassGetName String getRelatedClassName(
      Class<?> checkerClass, String replacement) {
    return checkerClass
        .getName()
        .replace("Checker", replacement)
        .replace("Subchecker", replacement);
  }

  // **********************************************************************
  // Misc. methods
  // **********************************************************************

  /** Specify supported lint options for all type-checkers. */
  @Override
  public Set<String> getSupportedLintOptions() {
    Set<String> lintSet = new HashSet<>(super.getSupportedLintOptions());
    lintSet.add("cast");
    lintSet.add("cast:redundant");
    lintSet.add("cast:unsafe");

    for (BaseTypeChecker checker : getSubcheckers()) {
      lintSet.addAll(checker.getSupportedLintOptions());
    }

    return Collections.unmodifiableSet(lintSet);
  }

  /**
   * Invokes the constructor belonging to the class named by {@code name} having the given parameter
   * types on the given arguments. Returns {@code null} if the class cannot be found. Otherwise,
   * throws an exception if there is trouble with the constructor invocation.
   *
   * @param <T> the type to which the constructor belongs
   * @param name the name of the class to which the constructor belongs
   * @param paramTypes the types of the constructor's parameters
   * @param args the arguments on which to invoke the constructor
   * @return the result of the constructor invocation on {@code args}, or null if the class does not
   *     exist
   */
  @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) // Intentional abuse
  public static <T> T invokeConstructorFor(
      @ClassGetName String name, Class<?>[] paramTypes, Object[] args) {

    // Load the class.
    Class<T> cls = null;
    try {
      cls = (Class<T>) Class.forName(name);
    } catch (Exception e) {
      // no class is found, simply return null
      return null;
    }

    assert cls != null : "reflectively loading " + name + " failed";

    // Invoke the constructor.
    try {
      Constructor<T> ctor = cls.getConstructor(paramTypes);
      return ctor.newInstance(args);
    } catch (Throwable t) {
      if (t instanceof InvocationTargetException) {
        Throwable err = t.getCause();
        if (err instanceof UserError || err instanceof TypeSystemError) {
          // Don't add more information about the constructor invocation.
          throw (RuntimeException) err;
        }
      }
      Throwable cause;
      String causeMessage;
      if (t instanceof InvocationTargetException) {
        cause = t.getCause();
        if (cause == null || cause.getMessage() == null) {
          causeMessage = t.getMessage();
        } else if (t.getMessage() == null) {
          causeMessage = cause.getMessage();
        } else {
          causeMessage = t.getMessage() + ": " + cause.getMessage();
        }
      } else {
        cause = t;
        causeMessage = (cause == null) ? "null" : cause.getMessage();
      }
      throw new BugInCF(
          cause,
          "Error when invoking constructor %s(%s) on args %s; cause: %s",
          name,
          StringsPlume.join(", ", paramTypes),
          Arrays.toString(args),
          causeMessage);
    }
  }

  @Override
  public BaseTypeVisitor<?> getVisitor() {
    return (BaseTypeVisitor<?>) super.getVisitor();
  }

  /**
   * Return the type factory associated with this checker.
   *
   * @return the type factory associated with this checker
   */
  public GenericAnnotatedTypeFactory<?, ?, ?, ?> getTypeFactory() {
    BaseTypeVisitor<?> visitor = getVisitor();
    // Avoid NPE if this method is called during initialization.
    if (visitor == null) {
      return null;
    }
    return visitor.getTypeFactory();
  }

  @Override
  public AnnotationProvider getAnnotationProvider() {
    return getTypeFactory();
  }

  /**
   * Returns the requested subchecker. A checker of a given class can only be run once, so this
   * returns the only such checker, or null if none was found. The caller must know the exact
   * checker class to request.
   *
   * @param checkerClass the class of the subchecker
   * @return the requested subchecker or null if not found
   */
  @SuppressWarnings("unchecked")
  public <T extends BaseTypeChecker> T getSubchecker(Class<T> checkerClass) {
    for (BaseTypeChecker checker : immediateSubcheckers) {
      if (checker.getClass() == checkerClass) {
        return (T) checker;
      }
    }

    return null;
  }

  /**
   * Returns the type factory used by a subchecker. Returns null if no matching subchecker was found
   * or if the type factory is null. The caller must know the exact checker class to request.
   *
   * @param checkerClass the class of the subchecker
   * @return the type factory of the requested subchecker or null if not found
   */
  @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) // Intentional abuse
  public <T extends GenericAnnotatedTypeFactory<?, ?, ?, ?>, U extends BaseTypeChecker>
      T getTypeFactoryOfSubchecker(Class<U> checkerClass) {
    BaseTypeChecker checker = getSubchecker(checkerClass);
    if (checker != null) {
      return (T) checker.getTypeFactory();
    }

    return null;
  }

  /*
   * Performs a depth first search for all checkers this checker depends on.
   * The depth first search ensures that the collection has the correct order the checkers need to be run in.
   *
   * Modifies the alreadyInitializedSubcheckerMap map by adding all recursively newly instantiated subcheckers' class objects and instances.
   * A LinkedHashMap is used because, unlike HashMap, it preserves the order in which entries were inserted.
   *
   * Returns the unmodifiable list of immediate subcheckers of this checker.
   */
  private List<BaseTypeChecker> instantiateSubcheckers(
      LinkedHashMap<Class<? extends BaseTypeChecker>, BaseTypeChecker>
          alreadyInitializedSubcheckerMap) {
    LinkedHashSet<Class<? extends BaseTypeChecker>> classesOfImmediateSubcheckers =
        getImmediateSubcheckerClasses();
    if (classesOfImmediateSubcheckers.isEmpty()) {
      return Collections.emptyList();
    }

    ArrayList<BaseTypeChecker> immediateSubcheckers =
        new ArrayList<>(classesOfImmediateSubcheckers.size());

    for (Class<? extends BaseTypeChecker> subcheckerClass : classesOfImmediateSubcheckers) {
      BaseTypeChecker subchecker = alreadyInitializedSubcheckerMap.get(subcheckerClass);
      if (subchecker != null) {
        // Add the already initialized subchecker to the list of immediate subcheckers so
        // that this checker can refer to it.
        immediateSubcheckers.add(subchecker);
        continue;
      }

      BaseTypeChecker instance;
      try {
        instance = subcheckerClass.getDeclaredConstructor().newInstance();
      } catch (Exception e) {
        throw new BugInCF("Could not create an instance of " + subcheckerClass);
      }

      instance.setProcessingEnvironment(this.processingEnv);
      instance.treePathCacher = this.getTreePathCacher();
      // Prevent the new checker from storing non-immediate subcheckers
      instance.subcheckers = Collections.emptyList();
      immediateSubcheckers.add(instance);
      instance.immediateSubcheckers =
          instance.instantiateSubcheckers(alreadyInitializedSubcheckerMap);
      instance.setParentChecker(this);
      alreadyInitializedSubcheckerMap.put(subcheckerClass, instance);
    }

    return Collections.unmodifiableList(immediateSubcheckers);
  }

  /**
   * Get the list of all subcheckers (if any). via the instantiateSubcheckers method. This list is
   * only non-empty for the one checker that runs all other subcheckers. These are recursively
   * instantiated via instantiateSubcheckers the first time the method is called if subcheckers is
   * null. Assumes all checkers run on the same thread.
   *
   * @return the list of all subcheckers (if any)
   */
  public List<BaseTypeChecker> getSubcheckers() {
    if (subcheckers == null) {
      // Instantiate the checkers this one depends on, if any.
      LinkedHashMap<Class<? extends BaseTypeChecker>, BaseTypeChecker> checkerMap =
          new LinkedHashMap<>(1);

      immediateSubcheckers = instantiateSubcheckers(checkerMap);

      subcheckers = Collections.unmodifiableList(new ArrayList<>(checkerMap.values()));
    }

    return subcheckers;
  }

  /** Get the shared TreePathCacher instance. */
  public TreePathCacher getTreePathCacher() {
    if (treePathCacher == null) {
      // In case it wasn't already set in instantiateSubcheckers.
      treePathCacher = new TreePathCacher();
    }
    return treePathCacher;
  }

  @Override
  protected void reportJavacError(TreePath p) {
    if (parentChecker == null) {
      // Only the parent checker should report the "type.checking.not.run" error.
      super.reportJavacError(p);
    }
  }

  // AbstractTypeProcessor delegation
  @Override
  public void typeProcess(TypeElement element, TreePath tree) {
    if (!getSubcheckers().isEmpty()) {
      // TODO: I expected this to only be necessary if (parentChecker == null).
      // However, the NestedAggregateChecker fails otherwise.
      messageStore.clear();
    }

    // Errors (or other messages) issued via
    //   SourceChecker#message(Diagnostic.Kind, Object, String, Object...)
    // are stored in messageStore until all checkers have processed this compilation unit.
    // All other messages are printed immediately.  This includes errors issued because the
    // checker threw an exception.

    // In order to run the next checker on this compilation unit even if the previous issued errors,
    // the next checker's errsOnLastExit needs to include all errors issued by previous checkers.

    Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
    Log log = Log.instance(context);

    int nerrorsOfAllPreviousCheckers = this.errsOnLastExit;
    for (BaseTypeChecker subchecker : getSubcheckers()) {
      subchecker.errsOnLastExit = nerrorsOfAllPreviousCheckers;
      subchecker.messageStore = messageStore;
      int errorsBeforeTypeChecking = log.nerrors;

      subchecker.typeProcess(element, tree);

      int errorsAfterTypeChecking = log.nerrors;
      nerrorsOfAllPreviousCheckers += errorsAfterTypeChecking - errorsBeforeTypeChecking;
    }

    this.errsOnLastExit = nerrorsOfAllPreviousCheckers;
    super.typeProcess(element, tree);

    if (!getSubcheckers().isEmpty()) {
      printStoredMessages(tree.getCompilationUnit());
      // Update errsOnLastExit to reflect the errors issued.
      this.errsOnLastExit = log.nerrors;
    }
  }

  /**
   * Like {@link SourceChecker#getSuppressWarningsPrefixes()}, but includes all prefixes supported
   * by this checker or any of its subcheckers. Does not guarantee that the result is in any
   * particular order. The result is immutable.
   *
   * @return the suppress warnings prefixes supported by this checker or any of its subcheckers
   */
  public Collection<String> getSuppressWarningsPrefixesOfSubcheckers() {
    if (this.suppressWarningsPrefixesOfSubcheckers == null) {
      Collection<String> prefixes = getSuppressWarningsPrefixes();
      for (BaseTypeChecker subchecker : getSubcheckers()) {
        prefixes.addAll(subchecker.getSuppressWarningsPrefixes());
      }
      this.suppressWarningsPrefixesOfSubcheckers = ImmutableSet.copyOf(prefixes);
    }
    return this.suppressWarningsPrefixesOfSubcheckers;
  }

  /** A cache for {@link #getUltimateParentChecker}. */
  @MonotonicNonNull BaseTypeChecker ultimateParentChecker;

  /**
   * Finds the ultimate parent checker of this checker. The ultimate parent checker is the checker
   * that the user actually requested, i.e. the one with no parent. The ultimate parent might be
   * this checker itself.
   *
   * @return the first checker in the parent checker chain with no parent checker of its own, i.e.
   *     the ultimate parent checker
   */
  public BaseTypeChecker getUltimateParentChecker() {
    if (ultimateParentChecker == null) {
      ultimateParentChecker = this;
      while (ultimateParentChecker.getParentChecker() instanceof BaseTypeChecker) {
        ultimateParentChecker = (BaseTypeChecker) ultimateParentChecker.getParentChecker();
      }
    }

    return ultimateParentChecker;
  }

  /**
   * {@inheritDoc}
   *
   * <p>This implementation collects needed warning suppressions for all subcheckers.
   */
  @Override
  protected void warnUnneededSuppressions() {
    if (parentChecker != null) {
      return;
    }

    if (!hasOption("warnUnneededSuppressions")) {
      return;
    }
    Set<Element> elementsWithSuppressedWarnings =
        new HashSet<>(this.elementsWithSuppressedWarnings);
    this.elementsWithSuppressedWarnings.clear();
    Set<String> prefixes = new HashSet<>(getSuppressWarningsPrefixes());
    Set<String> errorKeys = new HashSet<>(messagesProperties.stringPropertyNames());
    for (BaseTypeChecker subChecker : subcheckers) {
      elementsWithSuppressedWarnings.addAll(subChecker.elementsWithSuppressedWarnings);
      subChecker.elementsWithSuppressedWarnings.clear();
      prefixes.addAll(subChecker.getSuppressWarningsPrefixes());
      errorKeys.addAll(subChecker.messagesProperties.stringPropertyNames());
      subChecker.getVisitor().treesWithSuppressWarnings.clear();
    }
    warnUnneededSuppressions(elementsWithSuppressedWarnings, prefixes, errorKeys);

    getVisitor().treesWithSuppressWarnings.clear();
  }

  /**
   * Stores all messages issued by this checker and its subcheckers for the current compilation
   * unit. The messages are printed after all checkers have processed the current compilation unit.
   * The purpose is to sort messages, grouping together all messages about a particular line of
   * code.
   *
   * <p>If this checker has no subcheckers and is not a subchecker for any other checker, then
   * messageStore is null and messages will be printed as they are issued by this checker.
   */
  private TreeSet<CheckerMessage> messageStore = null;

  /**
   * If this is a compound checker or a subchecker of a compound checker, then the message is stored
   * until all messages from all checkers for the compilation unit are issued.
   *
   * <p>Otherwise, it prints the message.
   */
  @Override
  protected void printOrStoreMessage(
      Diagnostic.Kind kind, String message, Tree source, CompilationUnitTree root) {
    assert this.currentRoot == root;
    StackTraceElement[] trace = Thread.currentThread().getStackTrace();
    if (messageStore == null) {
      super.printOrStoreMessage(kind, message, source, root, trace);
    } else {
      CheckerMessage checkerMessage = new CheckerMessage(kind, message, source, this, trace);
      messageStore.add(checkerMessage);
    }
  }

  /**
   * Prints error messages for this checker and all subcheckers such that the errors are ordered by
   * line and column number and then by checker. (See {@link #compareCheckerMessages} for more
   * precise order.)
   *
   * @param unit current compilation unit
   */
  private void printStoredMessages(CompilationUnitTree unit) {
    for (CheckerMessage msg : messageStore) {
      super.printOrStoreMessage(msg.kind, msg.message, msg.source, unit, msg.trace);
    }
  }

  /** Represents a message (e.g., an error message) issued by a checker. */
  private static class CheckerMessage {
    /** The severity of the message. */
    final Diagnostic.Kind kind;
    /** The message itself. */
    final String message;
    /** The source code that the message is about. */
    final @InternedDistinct Tree source;
    /** Stores the stack trace when the message is created. */
    final StackTraceElement[] trace;

    /**
     * The checker that issued this message. The compound checker that depends on this checker uses
     * this to sort the messages.
     */
    final @InternedDistinct BaseTypeChecker checker;

    /**
     * Create a new CheckerMessage.
     *
     * @param kind kind of diagnostic, for example, error or warning
     * @param message error message that needs to be printed
     * @param source tree element causing the error
     * @param checker the type-checker in use
     * @param trace the stack trace when the message is created
     */
    private CheckerMessage(
        Diagnostic.Kind kind,
        String message,
        @FindDistinct Tree source,
        @FindDistinct BaseTypeChecker checker,
        StackTraceElement[] trace) {
      this.kind = kind;
      this.message = message;
      this.source = source;
      this.checker = checker;
      this.trace = trace;
    }

    @Override
    public boolean equals(@Nullable Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }

      CheckerMessage that = (CheckerMessage) o;
      return this.kind == that.kind
          && this.message.equals(that.message)
          && this.source == that.source
          && this.checker == that.checker;
    }

    @Override
    public int hashCode() {
      return Objects.hash(kind, message, source, checker);
    }

    @Override
    public String toString() {
      return "CheckerMessage{"
          + "kind="
          + kind
          + ", checker="
          + checker.getClass().getSimpleName()
          + ", message='"
          + message
          + '\''
          + ", source="
          + source
          + '}';
    }
  }

  /**
   * Compares two {@link CheckerMessage}s. Compares first by position at which the error will be
   * printed, then by kind of message, then by the message string, and finally by the order in which
   * the checkers run.
   *
   * @param o1 the first CheckerMessage
   * @param o2 the second CheckerMessage
   * @return a negative integer, zero, or a positive integer if the first CheckerMessage is less
   *     than, equal to, or greater than the second
   */
  private int compareCheckerMessages(CheckerMessage o1, CheckerMessage o2) {
    int byPos = InternalUtils.compareDiagnosticPosition(o1.source, o2.source);
    if (byPos != 0) {
      return byPos;
    }

    int kind = o1.kind.compareTo(o2.kind);
    if (kind != 0) {
      return kind;
    }

    int msgcmp = o1.message.compareTo(o2.message);
    if (msgcmp == 0) {
      // If the two messages are identical so far, it doesn't matter
      // from which checker they came.
      return 0;
    }

    // Sort by order in which the checkers are run. (All the subcheckers,
    // followed by the checker.)
    List<BaseTypeChecker> subcheckers = BaseTypeChecker.this.getSubcheckers();
    int o1Index = subcheckers.indexOf(o1.checker);
    int o2Index = subcheckers.indexOf(o2.checker);
    if (o1Index == -1) {
      o1Index = subcheckers.size();
    }
    if (o2Index == -1) {
      o2Index = subcheckers.size();
    }
    int checkercmp = Integer.compare(o1Index, o2Index);
    if (checkercmp == 0) {
      // If the two messages are from the same checker, sort by message.
      return msgcmp;
    } else {
      return checkercmp;
    }
  }

  @Override
  public void typeProcessingOver() {
    for (BaseTypeChecker checker : getSubcheckers()) {
      checker.typeProcessingOver();
    }

    super.typeProcessingOver();
  }

  @Override
  public Set<String> getSupportedOptions() {
    if (supportedOptions == null) {
      Set<String> options = new HashSet<>();
      options.addAll(super.getSupportedOptions());

      for (BaseTypeChecker checker : getSubcheckers()) {
        options.addAll(checker.getSupportedOptions());
      }

      options.addAll(
          expandCFOptions(Arrays.asList(this.getClass()), options.toArray(new String[0])));

      supportedOptions = Collections.unmodifiableSet(options);
    }
    return supportedOptions;
  }

  @Override
  public Map<String, String> getOptions() {
    if (this.options == null) {
      Map<String, String> options = new HashMap<>(super.getOptions());

      for (BaseTypeChecker checker : getSubcheckers()) {
        options.putAll(checker.getOptions());
      }
      this.options = Collections.unmodifiableMap(options);
    }

    return this.options;
  }

  /**
   * Like {@link #getOptions}, but only includes options provided to this checker. Does not include
   * those passed to subcheckers.
   *
   * @return the the active options for this checker, not including those passed to subcheckers
   */
  public Map<String, String> getOptionsNoSubcheckers() {
    return super.getOptions();
  }

  /**
   * Like {@link #hasOption}, but checks whether the given option is provided to this checker. Does
   * not consider those passed to subcheckers.
   *
   * @param name the name of the option to check
   * @return true if the option name was provided to this checker, false otherwise
   */
  public final boolean hasOptionNoSubcheckers(String name) {
    return getOptionsNoSubcheckers().containsKey(name);
  }

  /**
   * Return a list of additional stub files to be treated as if they had been written in a
   * {@code @StubFiles} annotation.
   *
   * @return stub files to be treated as if they had been written in a {@code @StubFiles} annotation
   */
  public List<String> getExtraStubFiles() {
    return new ArrayList<>();
  }

  @Override
  protected Object processArg(Object arg) {
    if (arg instanceof Collection) {
      Collection<?> carg = (Collection<?>) arg;
      return CollectionsPlume.mapList(this::processArg, carg);
    } else if (arg instanceof AnnotationMirror && getTypeFactory() != null) {
      return getTypeFactory()
          .getAnnotationFormatter()
          .formatAnnotationMirror((AnnotationMirror) arg);
    } else {
      return super.processArg(arg);
    }
  }

  @Override
  protected boolean shouldAddShutdownHook() {
    if (super.shouldAddShutdownHook() || getTypeFactory().getCFGVisualizer() != null) {
      return true;
    }
    for (BaseTypeChecker checker : getSubcheckers()) {
      if (checker.getTypeFactory().getCFGVisualizer() != null) {
        return true;
      }
    }
    return false;
  }

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

    CFGVisualizer<?, ?, ?> viz = getTypeFactory().getCFGVisualizer();
    if (viz != null) {
      viz.shutdown();
    }

    for (BaseTypeChecker checker : getSubcheckers()) {
      viz = checker.getTypeFactory().getCFGVisualizer();
      if (viz != null) {
        viz.shutdown();
      }
    }
  }
}
