package org.checkerframework.framework.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.jar.JarInputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import org.checkerframework.checker.signature.qual.FullyQualifiedName;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.SystemUtil;
import org.checkerframework.javacutil.UserError;
import org.plumelib.util.CollectionsPlume;

/**
 * This class behaves similarly to javac. CheckerMain does the following:
 *
 * <ul>
 *   <li>add the {@code javac.jar} to the runtime classpath of the process that runs the Checker
 *       Framework.
 *   <li>parse and implement any special options used by the Checker Framework, e.g., using
 *       "shortnames" for annotation processors
 *   <li>pass all remaining command-line arguments to the real javac
 * </ul>
 *
 * To debug this class, use the {@code -AoutputArgsToFile=FILENAME} command-line argument or {@code
 * -AoutputArgsToFile=-} to output to standard out.
 *
 * <p>"To run the Checker Framework" really means to run java, where the program being run is javac
 * and javac is passed a {@code -processor} command-line argument that mentions a Checker Framework
 * checker. There are 5 relevant classpaths: The classpath and bootclasspath when running java, and
 * the classpath, bootclasspath, and processorpath used by javac. The latter three are the only
 * important ones.
 *
 * <p>Note for developers: Try to limit the work done (and options interpreted) by CheckerMain,
 * because its functionality is not available to users who choose not to use the Checker Framework
 * javac script.
 */
public class CheckerMain {

  /**
   * Any exception thrown by the Checker Framework escapes to the command line.
   *
   * @param args command-line arguments
   */
  public static void main(String[] args) {
    final File pathToThisJar = new File(findPathTo(CheckerMain.class, false));
    ArrayList<String> alargs = new ArrayList<>(Arrays.asList(args));
    final CheckerMain program = new CheckerMain(pathToThisJar, alargs);
    final int exitStatus = program.invokeCompiler();
    System.exit(exitStatus);
  }

  /** The path to the javacJar to use. */
  protected final File javacJar;

  /** The path to the jar containing CheckerMain.class (i.e. checker.jar). */
  protected final File checkerJar;

  /** The path to checker-qual.jar. */
  protected final File checkerQualJar;

  /** The path to checker-util.jar. */
  protected final File checkerUtilJar;

  /** Compilation bootclasspath. */
  private final List<String> compilationBootclasspath;

  private final List<String> runtimeClasspath;

  private final List<String> jvmOpts;

  /**
   * Each element is either a classpath element (a directory or jar file) or is a classpath
   * (containing elements separated by File.pathSeparator). To produce the final classpath,
   * concatenate them all (separated by File.pathSeparator).
   */
  private final List<String> cpOpts;

  /** Processor path options. */
  private final List<String> ppOpts;

  /** Arguments to the Checker Framework. */
  private final List<String> toolOpts;

  /** Command-line argument files (specified with @ on the command line). */
  private final List<File> argListFiles;

  /**
   * Option name for specifying an alternative checker-qual.jar location. The accompanying value
   * MUST be the path to the jar file (NOT the path to its encompassing directory)
   */
  public static final String CHECKER_QUAL_PATH_OPT = "-checkerQualJar";

  /**
   * Option name for specifying an alternative checker-util.jar location. The accompanying value
   * MUST be the path to the jar file (NOT the path to its encompassing directory)
   */
  public static final String CHECKER_UTIL_PATH_OPT = "-checkerUtilJar";

  /**
   * Option name for specifying an alternative javac.jar location. The accompanying value MUST be
   * the path to the jar file (NOT the path to its encompassing directory)
   */
  public static final String JAVAC_PATH_OPT = "-javacJar";

  /**
   * Option name for specifying an alternative jdk.jar location. The accompanying value MUST be the
   * path to the jar file (NOT the path to its encompassing directory)
   */
  public static final String JDK_PATH_OPT = "-jdkJar";

  /**
   * Construct all the relevant file locations and Java version given the path to this jar and a set
   * of directories in which to search for jars.
   */
  public CheckerMain(final File checkerJar, final List<String> args) {

    this.checkerJar = checkerJar;
    final File searchPath = checkerJar.getParentFile();

    replaceShorthandProcessor(args);
    argListFiles = collectArgFiles(args);

    this.checkerQualJar =
        extractFileArg(CHECKER_QUAL_PATH_OPT, new File(searchPath, "checker-qual.jar"), args);

    this.checkerUtilJar =
        extractFileArg(CHECKER_UTIL_PATH_OPT, new File(searchPath, "checker-util.jar"), args);

    this.javacJar = extractFileArg(JAVAC_PATH_OPT, new File(searchPath, "javac.jar"), args);

    this.compilationBootclasspath = createCompilationBootclasspath(args);
    this.runtimeClasspath = createRuntimeClasspath(args);
    this.jvmOpts = extractJvmOpts(args);

    this.cpOpts = createCpOpts(args);
    this.ppOpts = createPpOpts(args);
    this.toolOpts = args;

    assertValidState();
  }

  /** Assert that required jars exist. */
  protected void assertValidState() {
    if (SystemUtil.getJreVersion() < 9) {
      assertFilesExist(Arrays.asList(javacJar, checkerJar, checkerQualJar, checkerUtilJar));
    } else {
      assertFilesExist(Arrays.asList(checkerJar, checkerQualJar, checkerUtilJar));
    }
  }

  public void addToClasspath(List<String> cpOpts) {
    this.cpOpts.addAll(cpOpts);
  }

  public void addToProcessorpath(List<String> ppOpts) {
    this.ppOpts.addAll(ppOpts);
  }

  public void addToRuntimeClasspath(List<String> runtimeClasspathOpts) {
    this.runtimeClasspath.addAll(runtimeClasspathOpts);
  }

  protected List<String> createRuntimeClasspath(final List<String> argsList) {
    return new ArrayList<>(Arrays.asList(javacJar.getAbsolutePath()));
  }

  /**
   * Returns the compilation bootclasspath from {@code argsList}.
   *
   * @param argsList args to add
   * @return the compilation bootclasspath from {@code argsList}
   */
  protected List<String> createCompilationBootclasspath(final List<String> argsList) {
    return extractBootClassPath(argsList);
  }

  protected List<String> createCpOpts(final List<String> argsList) {
    final List<String> extractedOpts = extractCpOpts(argsList);
    extractedOpts.add(0, this.checkerQualJar.getAbsolutePath());
    extractedOpts.add(0, this.checkerUtilJar.getAbsolutePath());

    return extractedOpts;
  }

  /**
   * Returns processor path options.
   *
   * <p>This method assumes that createCpOpts has already been run.
   *
   * @param argsList arguments
   * @return processor path options
   */
  protected List<String> createPpOpts(final List<String> argsList) {
    final List<String> extractedOpts = new ArrayList<>(extractPpOpts(argsList));
    if (extractedOpts.isEmpty()) {
      // If processorpath is not provided, then javac uses the classpath.
      // CheckerMain always supplies a processorpath, so if the user
      // didn't specify a processorpath, then use the classpath.
      extractedOpts.addAll(this.cpOpts);
    }
    extractedOpts.add(0, this.checkerJar.getAbsolutePath());
    extractedOpts.add(0, this.checkerUtilJar.getAbsolutePath());

    return extractedOpts;
  }

  /**
   * Return the arguments that start with @ and therefore are files that contain javac arguments.
   *
   * @param args a list of command-line arguments; is not modified
   * @return a List of files representing all arguments that started with @
   */
  protected List<File> collectArgFiles(final List<String> args) {
    final List<File> argListFiles = new ArrayList<>();
    for (final String arg : args) {
      if (arg.startsWith("@")) {
        argListFiles.add(new File(arg.substring(1)));
      }
    }

    return argListFiles;
  }

  /**
   * Remove the argument given by argumentName and the subsequent value from the list args if
   * present. Return the subsequent value.
   *
   * @param argumentName a command-line option name whose argument to extract
   * @param alternative default value to return if argumentName does not appear in args
   * @param args the current list of arguments
   * @return the string that follows argumentName if argumentName is in args, or alternative if
   *     argumentName is not present in args
   */
  protected static String extractArg(
      final String argumentName, final String alternative, final List<String> args) {
    int i = args.indexOf(argumentName);
    if (i == -1) {
      return alternative;
    } else if (i == args.size() - 1) {
      throw new BugInCF("Command line contains " + argumentName + " but no value following it");
    } else {
      args.remove(i);
      return args.remove(i);
    }
  }

  /**
   * Remove the argument given by argumentName and the subsequent value from the list args if
   * present. Return the subsequent value wrapped as a File.
   *
   * @param argumentName argument to extract
   * @param alternative file to return if argumentName is not found in args
   * @param args the current list of arguments
   * @return the string that follows argumentName wrapped as a File if argumentName is in args or
   *     alternative if argumentName is not present in args
   */
  protected static File extractFileArg(
      final String argumentName, final File alternative, final List<String> args) {
    final String filePath = extractArg(argumentName, null, args);
    if (filePath == null) {
      return alternative;
    } else {
      return new File(filePath);
    }
  }

  /**
   * Find all args that match the given pattern and extract their index 1 group. Add all the index 1
   * groups to the returned list. Remove all matching args from the input args list.
   *
   * @param pattern a pattern with at least one matching group
   * @param allowEmpties whether or not to add empty group(1) matches to the returned list
   * @param args the arguments to extract from
   * @return a list of arguments from the first group that matched the pattern for each input args
   *     or the empty list if there were none
   */
  protected static List<String> extractOptWithPattern(
      final Pattern pattern, boolean allowEmpties, final List<String> args) {
    final List<String> matchedArgs = new ArrayList<>();

    int i = 0;
    while (i < args.size()) {
      final Matcher matcher = pattern.matcher(args.get(i));
      if (matcher.matches()) {
        final String arg = matcher.group(1).trim();

        if (!arg.isEmpty() || allowEmpties) {
          matchedArgs.add(arg);
        }

        args.remove(i);
      } else {
        i++;
      }
    }

    return matchedArgs;
  }

  /**
   * A pattern to match bootclasspath prepend entries, used to construct one {@code
   * -Xbootclasspath/p:} command-line argument.
   */
  protected static final Pattern BOOT_CLASS_PATH_REGEX =
      Pattern.compile("^(?:-J)?-Xbootclasspath/p:(.*)$");

  // TODO: Why does this treat -J and -J-X the same?  They have different semantics, don't they?
  /**
   * Remove all {@code -Xbootclasspath/p:} or {@code -J-Xbootclasspath/p:} arguments from args and
   * add them to the returned list.
   *
   * @param args the arguments to extract from
   * @return all non-empty arguments matching BOOT_CLASS_PATH_REGEX or an empty list if there were
   *     none
   */
  protected static List<String> extractBootClassPath(final List<String> args) {
    return extractOptWithPattern(BOOT_CLASS_PATH_REGEX, false, args);
  }

  /** Matches all {@code -J} arguments. */
  protected static final Pattern JVM_OPTS_REGEX = Pattern.compile("^(?:-J)(.*)$");

  /**
   * Remove all {@code -J} arguments from {@code args} and add them to the returned list (without
   * the {@code -J} prefix).
   *
   * @param args the arguments to extract from
   * @return all {@code -J} arguments (without the {@code -J} prefix) or an empty list if there were
   *     none
   */
  protected static List<String> extractJvmOpts(final List<String> args) {
    return extractOptWithPattern(JVM_OPTS_REGEX, false, args);
  }

  /**
   * Return the last {@code -cp} or {@code -classpath} option. If no {@code -cp} or {@code
   * -classpath} arguments were present, then return the CLASSPATH environment variable (if set)
   * followed by the current directory.
   *
   * <p>Also removes all {@code -cp} and {@code -classpath} options from args.
   *
   * @param args a list of arguments to extract from; is side-effected by this
   * @return collection of classpaths to concatenate to use when calling javac.jar
   */
  protected static List<String> extractCpOpts(final List<String> args) {
    List<String> actualArgs = new ArrayList<>();

    String lastCpArg = null;

    for (int i = 0; i < args.size(); i++) {
      if ((args.get(i).equals("-cp") || args.get(i).equals("-classpath"))
          && (i + 1 < args.size())) {
        args.remove(i);
        // Every classpath entry overrides the one before it.
        lastCpArg = args.remove(i);
        // re-process whatever is currently at element i
        i--;
      }
    }

    // The logic below is exactly what the javac script does.  If no command-line classpath is
    // specified, use the "CLASSPATH" environment variable followed by the current directory.
    if (lastCpArg == null) {
      final String systemClassPath = System.getenv("CLASSPATH");
      if (systemClassPath != null && !systemClassPath.trim().isEmpty()) {
        actualArgs.add(systemClassPath.trim());
      }

      actualArgs.add(".");
    } else {
      actualArgs.add(lastCpArg);
    }

    return actualArgs;
  }

  /**
   * Remove the {@code -processorpath} options and their arguments from args. Return the last
   * argument.
   *
   * @param args a list of arguments to extract from
   * @return the arguments that should be put on the processorpath when calling javac.jar
   */
  protected static List<String> extractPpOpts(final List<String> args) {
    String path = null;

    for (int i = 0; i < args.size(); i++) {
      if (args.get(i).equals("-processorpath") && (i + 1 < args.size())) {
        args.remove(i);
        path = args.remove(i);
        // re-process whatever is currently at element i
        i--;
      }
    }

    if (path != null) {
      return Collections.singletonList(path);
    } else {
      return Collections.emptyList();
    }
  }

  protected void addMainToArgs(final List<String> args) {
    args.add("com.sun.tools.javac.Main");
  }

  /** Invoke the compiler with all relevant jars on its classpath and/or bootclasspath. */
  public List<String> getExecArguments() {
    List<String> args = new ArrayList<>(jvmOpts.size() + cpOpts.size() + toolOpts.size() + 7);

    // TODO: do we need java.exe on Windows?
    final String java = "java";
    args.add(java);

    if (SystemUtil.getJreVersion() == 8) {
      args.add("-Xbootclasspath/p:" + String.join(File.pathSeparator, runtimeClasspath));
    } else {
      args.addAll(
          Arrays.asList(
              "--illegal-access=warn",
              "--add-opens",
              "jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED"));
    }

    args.add("-classpath");
    args.add(String.join(File.pathSeparator, runtimeClasspath));
    args.add("-ea");
    // com.sun.tools needs to be enabled separately
    args.add("-ea:com.sun.tools...");

    args.addAll(jvmOpts);

    addMainToArgs(args);

    if (!argsListHasClassPath(argListFiles)) {
      args.add("-classpath");
      args.add(quote(concatenatePaths(cpOpts)));
    }
    if (!argsListHasProcessorPath(argListFiles)) {
      args.add("-processorpath");
      args.add(quote(concatenatePaths(ppOpts)));
    }

    if (SystemUtil.getJreVersion() == 8) {
      // No classes on the compilation bootclasspath will be loaded
      // during compilation, but the classes are read by the compiler
      // without loading them.  The compiler assumes that any class on
      // this bootclasspath will be on the bootclasspath of the JVM used
      // to later run the classfiles that Javac produces.
      args.add("-Xbootclasspath/p:" + String.join(File.pathSeparator, compilationBootclasspath));

      // We currently provide a Java 8 JDK and want to be runnable
      // on a Java 8 JVM. So set source/target to 8.
      args.add("-source");
      args.add("8");
      args.add("-target");
      args.add("8");
    }

    args.addAll(toolOpts);
    return args;
  }

  /** Given a list of paths, concatenate them to form a single path. Also expand wildcards. */
  private String concatenatePaths(List<String> paths) {
    List<String> elements = new ArrayList<>();
    for (String path : paths) {
      for (String element : path.split(File.pathSeparator)) {
        elements.addAll(expandWildcards(element));
      }
    }
    return String.join(File.pathSeparator, elements);
  }

  /** The string "/*" (on Unix). */
  private static final String FILESEP_STAR = File.separator + "*";

  /**
   * Given a path element that might be a wildcard, return a list of the elements it expands to. If
   * the element isn't a wildcard, return a singleton list containing the argument.
   */
  private List<String> expandWildcards(String pathElement) {
    if (pathElement.equals("*")) {
      return jarFiles(".");
    } else if (pathElement.endsWith(FILESEP_STAR)) {
      return jarFiles(pathElement.substring(0, pathElement.length() - 1));
    } else if (pathElement.equals("")) {
      return Collections.emptyList();
    } else {
      return Collections.singletonList(pathElement);
    }
  }

  /**
   * Returns all the .jar and .JAR files in the given directory.
   *
   * @param directory a directory
   * @return all the .jar and .JAR files in the given directory
   */
  private List<String> jarFiles(String directory) {
    File dir = new File(directory);
    return Arrays.asList(dir.list((d, name) -> name.endsWith(".jar") || name.endsWith(".JAR")));
  }

  /** Invoke the compiler with all relevant jars on its classpath and/or bootclasspath. */
  public int invokeCompiler() {
    List<String> args = getExecArguments();

    for (int i = 0; i < args.size(); i++) {
      String arg = args.get(i);

      if (arg.startsWith("-AoutputArgsToFile=")) {
        String fileName = arg.substring(19);
        args.remove(i);
        outputArgumentsToFile(fileName, args);
        break;
      }
    }

    // Actually invoke the compiler
    return ExecUtil.execute(args.toArray(new String[args.size()]), System.out, System.err);
  }

  private static void outputArgumentsToFile(String outputFilename, List<String> args) {
    if (outputFilename != null) {
      String errorMessage = null;

      try {
        PrintWriter writer =
            (outputFilename.equals("-")
                ? new PrintWriter(System.out)
                : new PrintWriter(outputFilename, "UTF-8"));
        for (int i = 0; i < args.size(); i++) {
          String arg = args.get(i);

          // We would like to include the filename of the argfile instead of its contents.
          // The problem is that the file will sometimes disappear by the time the user
          // can look at or run the resulting script. Maven deletes the argfile very
          // shortly after it has been handed off to javac, for example. Ideally we would
          // print the argfile filename as a comment but the resulting file couldn't then
          // be run as a script on Unix or Windows.
          if (arg.startsWith("@")) {
            // Read argfile and include its parameters in the output file.
            String inputFilename = arg.substring(1);

            BufferedReader br = new BufferedReader(new FileReader(inputFilename));
            String line;
            while ((line = br.readLine()) != null) {
              writer.print(line);
              writer.print(" ");
            }
            br.close();
          } else {
            writer.print(arg);
            writer.print(" ");
          }
        }
        writer.close();
      } catch (IOException e) {
        errorMessage = e.toString();
      }

      if (errorMessage != null) {
        System.err.println(
            "Failed to output command-line arguments to file "
                + outputFilename
                + " due to exception: "
                + errorMessage);
      }
    }
  }

  /**
   * Returns true if some @arglist file sets the classpath.
   *
   * @param argListFiles command-line argument files (specified with @ on the command line)
   */
  private static boolean argsListHasClassPath(final List<File> argListFiles) {
    for (final String arg : expandArgFiles(argListFiles)) {
      if (arg.contains("-classpath") || arg.contains("-cp")) {
        return true;
      }
    }

    return false;
  }

  /**
   * Returns true if some @arglist file sets the processorpath.
   *
   * @param argListFiles command-line argument files (specified with @ on the command line)
   */
  private static boolean argsListHasProcessorPath(final List<File> argListFiles) {
    for (final String arg : expandArgFiles(argListFiles)) {
      if (arg.contains("-processorpath")) {
        return true;
      }
    }

    return false;
  }

  /**
   * Return all the lines in all the files.
   *
   * @param files a list of files
   * @return a list of all the lines in all the files
   */
  protected static List<String> expandArgFiles(final List<File> files) {
    final List<String> content = new ArrayList<>();
    for (final File file : files) {
      try {
        content.addAll(Files.readAllLines(file.toPath()));
      } catch (final IOException exc) {
        throw new RuntimeException("Could not open file: " + file.getAbsolutePath(), exc);
      }
    }
    return content;
  }

  /**
   * Find the jar file or directory containing the .class file from which cls was loaded.
   *
   * @param cls the class whose .class file we wish to locate; if null, CheckerMain.class
   * @param errIfFromDirectory if false, throw an exception if the file was loaded from a directory
   */
  public static String findPathTo(Class<?> cls, boolean errIfFromDirectory)
      throws IllegalStateException {
    if (cls == null) {
      cls = CheckerMain.class;
    }
    String name = cls.getName();
    String classFileName;
    /* name is something like pakkage.name.ContainingClass$ClassName. We need to turn this into ContainingClass$ClassName.class. */
    {
      int idx = name.lastIndexOf('.');
      classFileName = (idx == -1 ? name : name.substring(idx + 1)) + ".class";
    }

    String uri = cls.getResource(classFileName).toString();
    if (uri.startsWith("file:")) {
      if (errIfFromDirectory) {
        return uri;
      } else {
        throw new IllegalStateException(
            "This class has been loaded from a directory and not from a jar file.");
      }
    }
    if (!uri.startsWith("jar:file:")) {
      int idx = uri.indexOf(':');
      String protocol = idx == -1 ? "(unknown)" : uri.substring(0, idx);
      throw new IllegalStateException(
          "This class has been loaded remotely via the "
              + protocol
              + " protocol. Only loading from a jar on the local file system is supported.");
    }

    int idx = uri.indexOf('!');
    // Sanity check
    if (idx == -1) {
      throw new IllegalStateException(
          "You appear to have loaded this class from a local jar file, but URI has no \"!\": "
              + uri);
    }

    try {
      String fileName =
          URLDecoder.decode(
              uri.substring("jar:file:".length(), idx), Charset.defaultCharset().name());
      return new File(fileName).getAbsolutePath();
    } catch (UnsupportedEncodingException e) {
      throw new BugInCF("Default charset doesn't exist. Your VM is borked.");
    }
  }

  /**
   * Assert that all files in the list exist and if they don't, throw a RuntimeException with a list
   * of the files that do not exist.
   *
   * @param expectedFiles files that must exist
   */
  private static void assertFilesExist(final List<File> expectedFiles) {
    final List<File> missingFiles = new ArrayList<>();
    for (final File file : expectedFiles) {
      if (file == null) {
        throw new RuntimeException("Null passed to assertFilesExist");
      }
      if (!file.exists()) {
        missingFiles.add(file);
      }
    }

    if (!missingFiles.isEmpty()) {
      if (missingFiles.size() == 1) {
        File missingFile = missingFiles.get(0);
        if (missingFile.getName().equals("javac.jar")) {
          throw new UserError(
              "Could not find "
                  + missingFile.getAbsolutePath()
                  + ". This may be because you built the Checker Framework under Java 11 but are"
                  + " running it under Java 8.");
        }
      }
      List<String> missingAbsoluteFilenames =
          CollectionsPlume.mapList(File::getAbsolutePath, missingFiles);
      throw new RuntimeException(
          "The following files could not be located: "
              + String.join(", ", missingAbsoluteFilenames));
    }
  }

  private static String quote(final String str) {
    if (str.contains(" ")) {
      if (str.contains("\"")) {
        throw new BugInCF(
            "Don't know how to quote a string containing a double-quote character " + str);
      }
      return "\"" + str + "\"";
    }
    return str;
  }

  ///////////////////////////////////////////////////////////////////////////
  /// Shorthand checker names
  ///

  /** Processor shorthand is enabled for processors in this directory in checker.jar. */
  protected static final String CHECKER_BASE_DIR_NAME = "org/checkerframework/checker/";
  /** Processor shorthand is enabled for processors in this directory in checker.jar. */
  protected static final String COMMON_BASE_DIR_NAME = "org/checkerframework/common/";

  /**
   * Returns true if processorString, once transformed into fully-qualified form, is present in
   * fullyQualifiedCheckerNames. Used by SourceChecker to determine whether a class is annotated for
   * any processor that is being run.
   *
   * @param processorString the name of a single processor, not a comma-separated list of processors
   * @param fullyQualifiedCheckerNames a list of fully-qualified checker names
   * @return true if the fully-qualified version of {@code processorString} is in {@code
   *     fullyQualifiedCheckerNames}
   */
  public static boolean matchesCheckerOrSubcheckerFromList(
      final String processorString, List<@FullyQualifiedName String> fullyQualifiedCheckerNames) {
    if (processorString.contains(",")) {
      return false; // Do not process strings containing multiple processors.
    }

    return fullyQualifiedCheckerNames.contains(
        unshorthandProcessorNames(processorString, fullyQualifiedCheckerNames, true));
  }

  /**
   * For every "-processor" argument in args, replace its immediate successor argument using
   * unabbreviateProcessorNames.
   */
  protected void replaceShorthandProcessor(final List<String> args) {
    for (int i = 0; i < args.size(); i++) {
      final int nextIndex = i + 1;
      if (args.size() > nextIndex) {
        if (args.get(i).equals("-processor")) {
          final String replacement =
              unshorthandProcessorNames(args.get(nextIndex), getAllCheckerClassNames(), false);
          args.remove(nextIndex);
          args.add(nextIndex, replacement);
        }
      }
    }
  }

  /**
   * Returns the list of fully qualified names of the checkers found in checker.jar. This covers
   * only checkers with the name ending in "Checker". Checkers with a name ending in "Subchecker"
   * are not included in the returned list. Note however that it is possible for a checker with the
   * name ending in "Checker" to be used as a subchecker.
   *
   * @return fully qualified names of the checkers found in checker.jar
   */
  private List<@FullyQualifiedName String> getAllCheckerClassNames() {
    ArrayList<@FullyQualifiedName String> checkerClassNames = new ArrayList<>();
    try {
      final JarInputStream checkerJarIs = new JarInputStream(new FileInputStream(checkerJar));
      ZipEntry entry;
      while ((entry = checkerJarIs.getNextEntry()) != null) {
        final String name = entry.getName();
        // Checkers ending in "Subchecker" are not included in this list used by CheckerMain.
        if ((name.startsWith(CHECKER_BASE_DIR_NAME) || name.startsWith(COMMON_BASE_DIR_NAME))
            && name.endsWith("Checker.class")) {
          // Forward slash is used instead of File.separator because checker.jar uses / as
          // the separator.
          @SuppressWarnings("signature") // string manipulation
          @FullyQualifiedName String fqName =
              String.join(".", name.substring(0, name.length() - ".class".length()).split("/"));
          checkerClassNames.add(fqName);
        }
      }
      checkerJarIs.close();
    } catch (IOException e) {
      // Issue a warning instead of aborting execution.
      System.err.printf(
          "Could not read %s. Shorthand processor names will not work.%n", checkerJar);
    }

    return checkerClassNames;
  }

  /**
   * Takes a string of comma-separated processor names, and expands any shorthands to
   * fully-qualified names from the fullyQualifiedCheckerNames list. For example:
   *
   * <pre>
   * NullnessChecker &rarr; org.checkerframework.checker.nullness.NullnessChecker
   * nullness &rarr; org.checkerframework.checker.nullness.NullnessChecker
   * NullnessChecker,RegexChecker &rarr; org.checkerframework.checker.nullness.NullnessChecker,org.checkerframework.checker.regex.RegexChecker
   * </pre>
   *
   * Note, a processor entry only gets replaced if it contains NO "." (i.e., it is not qualified by
   * a package name) and can be found under the package org.checkerframework.checker in checker.jar.
   *
   * @param processorsString a comma-separated string identifying processors
   * @param fullyQualifiedCheckerNames a list of fully-qualified checker names to match
   *     processorsString against
   * @param allowSubcheckers whether to match against fully qualified checker names ending with
   *     "Subchecker"
   * @return processorsString where all shorthand references to Checker Framework built-in checkers
   *     are replaced with fully-qualified references
   */
  protected static String unshorthandProcessorNames(
      final String processorsString,
      List<@FullyQualifiedName String> fullyQualifiedCheckerNames,
      boolean allowSubcheckers) {
    final String[] processors = processorsString.split(",");
    for (int i = 0; i < processors.length; i++) {
      if (!processors[i].contains(".")) { // Not already fully qualified
        processors[i] =
            unshorthandProcessorName(processors[i], fullyQualifiedCheckerNames, allowSubcheckers);
      }
    }

    return String.join(",", processors);
  }

  /**
   * Given a processor name, tries to expand it to a checker in the fullyQualifiedCheckerNames list.
   * Returns that expansion, or the argument itself if the expansion fails.
   *
   * @param processorName a processor name, possibly in shorthand
   * @param fullyQualifiedCheckerNames all checker names
   * @param allowSubcheckers whether to match subcheckers as well as checkers
   * @return the fully-qualified version of {@code processorName} in {@code
   *     fullyQualifiedCheckerNames}, or else {@code processorName} itself
   */
  private static String unshorthandProcessorName(
      final String processorName,
      List<@FullyQualifiedName String> fullyQualifiedCheckerNames,
      boolean allowSubcheckers) {
    for (final String name : fullyQualifiedCheckerNames) {
      boolean tryMatch = false;
      String[] checkerPath = name.substring(0, name.length() - "Checker".length()).split("\\.");
      String checkerNameShort = checkerPath[checkerPath.length - 1];
      String checkerName = checkerNameShort + "Checker";

      if (name.endsWith("Checker")) {
        checkerPath = name.substring(0, name.length() - "Checker".length()).split("\\.");
        checkerNameShort = checkerPath[checkerPath.length - 1];
        checkerName = checkerNameShort + "Checker";
        tryMatch = true;
      } else if (allowSubcheckers && name.endsWith("Subchecker")) {
        checkerPath = name.substring(0, name.length() - "Subchecker".length()).split("\\.");
        checkerNameShort = checkerPath[checkerPath.length - 1];
        checkerName = checkerNameShort + "Subchecker";
        tryMatch = true;
      }

      if (tryMatch) {
        if (processorName.equalsIgnoreCase(checkerName)
            || processorName.equalsIgnoreCase(checkerNameShort)) {
          return name;
        }
      }
    }

    return processorName; // If not matched, return the input string.
  }

  /**
   * Given a shorthand processor name, returns true if it can be expanded to a checker in the
   * fullyQualifiedCheckerNames list.
   *
   * @param processorName a string identifying one processor
   * @param fullyQualifiedCheckerNames a list of fully-qualified checker names to match
   *     processorName against
   * @param allowSubcheckers whether to match against fully qualified checker names ending with
   *     "Subchecker"
   * @return true if the shorthand processor name can be expanded to a checker in {@code
   *     fullyQualifiedCheckerNames}
   */
  public static boolean matchesFullyQualifiedProcessor(
      final String processorName,
      List<@FullyQualifiedName String> fullyQualifiedCheckerNames,
      boolean allowSubcheckers) {
    return !processorName.equals(
        unshorthandProcessorName(processorName, fullyQualifiedCheckerNames, allowSubcheckers));
  }
}
