package org.checkerframework.framework.stub;

import com.github.javaparser.ParseResult;
import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.Position;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.expr.ArrayInitializerExpr;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
import com.github.javaparser.ast.expr.MemberValuePair;
import com.github.javaparser.ast.expr.NormalAnnotationExpr;
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
import com.github.javaparser.ast.visitor.GenericListVisitorAdapter;
import com.github.javaparser.utils.CollectionStrategy;
import com.github.javaparser.utils.ParserCollectionStrategy;
import com.github.javaparser.utils.PositionUtils;
import com.github.javaparser.utils.ProjectRoot;
import com.github.javaparser.utils.SourceRoot;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.reflect.ClassPath;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import org.checkerframework.javacutil.BugInCF;
import org.plumelib.util.CollectionsPlume;

/**
 * Process Java source files to remove annotations that ought to be inferred.
 *
 * <p>Removes annotations from all files in the given directories. Modifies the files in place.
 *
 * <p>Does not remove trusted annotations: those that the checker trusts rather than verifies.
 *
 * <p>Does not remove annotations at locations where inference does no work:
 *
 * <ul>
 *   <li>within the scope of a relevant @SuppressWarnings
 *   <li>within the scope of @IgnoreInWholeProgramInference or an annotation meta-annotated with
 *       that, such as @Option
 * </ul>
 *
 * After removing annotations, javac may issue "warning: [cast] redundant cast to ..." if {@code
 * -Alint:cast} (or {@code -Alint:all} which implies it) is passed to javac. You can suppress the
 * warning by passing {@code -Alint:-cast} to javac.
 */
public class RemoveAnnotationsForInference {

  /**
   * Processes each provided command-line argument; see {@link RemoveAnnotationsForInference class
   * documentation} for details.
   *
   * @param args command-line arguments: directories to process
   */
  public static void main(String[] args) {
    if (args.length < 1) {
      System.err.println("Usage: provide one or more directory names to process");
      System.exit(1);
    }
    for (String arg : args) {
      process(arg);
    }
  }

  /**
   * Maps from simple names to fully-qualified names of annotations. (Actually, it includes every
   * class on the classpath.)
   */
  static Multimap<String, String> simpleToFullyQualified = ArrayListMultimap.create();

  static {
    try {
      ClassPath cp = ClassPath.from(RemoveAnnotationsForInference.class.getClassLoader());
      for (ClassPath.ClassInfo ci : cp.getTopLevelClasses()) {
        // There is no way to determine whether `ci` represents an annotation, without loading it.
        // I could filter using a heuristic: only include classes in a package named "qual".
        simpleToFullyQualified.put(ci.getSimpleName(), ci.getName());
      }
    } catch (IOException e) {
      throw new BugInCF(e);
    }
  }

  /**
   * Process each file in the given directory; see the {@link RemoveAnnotationsForInference class
   * documentation} for details.
   *
   * @param dir directory to process
   */
  private static void process(String dir) {

    Path root = JavaStubifier.dirnameToPath(dir);

    RemoveAnnotationsCallback rac = new RemoveAnnotationsCallback();
    CollectionStrategy strategy = new ParserCollectionStrategy();
    // Required to include directories that contain a module-info.java, which don't parse by
    // default.
    strategy.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_11);
    ProjectRoot projectRoot = strategy.collect(root);

    for (SourceRoot sourceRoot : projectRoot.getSourceRoots()) {
      try {
        sourceRoot.parse("", rac);
      } catch (IOException e) {
        throw new BugInCF(e);
      }
    }
  }

  /**
   * Callback to process each Java file; see the {@link RemoveAnnotationsForInference class
   * documentation} for details.
   */
  private static class RemoveAnnotationsCallback implements SourceRoot.Callback {
    /** The visitor instance. */
    private final RemoveAnnotationsVisitor rav = new RemoveAnnotationsVisitor();

    @Override
    public Result process(Path localPath, Path absolutePath, ParseResult<CompilationUnit> result) {
      Optional<CompilationUnit> opt = result.getResult();
      if (opt.isPresent()) {
        CompilationUnit cu = opt.get();
        List<AnnotationExpr> removals = rav.visit(cu, null);
        removeAnnotations(absolutePath, removals);
      }
      return Result.DONT_SAVE;
    }
  }

  // An earlier implementation used ModifierVisitor.  However, JavaParser's unparser can change
  // the structure of the program. For example, it changes `protected @Nullable Object x;` to
  // `@Nullable protected Object x;` which yields a type.anno.before.modifier error.

  /**
   * Rewrites the file in place, removing the given annotations from it.
   *
   * @param absolutePath the path to the file
   * @param removals the annotations to remove
   */
  static void removeAnnotations(Path absolutePath, List<AnnotationExpr> removals) {
    if (removals.isEmpty()) {
      return;
    }

    List<String> lines;
    try {
      lines = Files.readAllLines(absolutePath);
    } catch (IOException e) {
      System.out.printf("Problem reading %s: %s%n", absolutePath, e.getMessage());
      System.exit(1);
      throw new Error("unreachable");
    }

    PositionUtils.sortByBeginPosition(removals);
    Collections.reverse(removals);

    // This code (correctly) assumes that no element of `removals` is contained within another.
    for (AnnotationExpr removal : removals) {
      Position begin = removal.getBegin().get();
      Position end = removal.getEnd().get();
      int beginLine = begin.line - 1;
      int beginColumn = begin.column - 1;
      int endLine = end.line - 1;
      int endColumn = end.column; // a JavaParser range is inclusive of the character at "end"
      if (beginLine == endLine) {
        String line = lines.get(beginLine);
        String prefix = line.substring(0, beginColumn);
        String suffix = line.substring(endColumn);

        // Remove whitespace to beautify formatting.
        suffix = CharMatcher.whitespace().trimLeadingFrom(suffix);
        if (suffix.startsWith("[")) {
          prefix = CharMatcher.whitespace().trimTrailingFrom(prefix);
        }

        String newLine = prefix + suffix;
        replaceLine(lines, beginLine, newLine);
      } else {
        String newLastLine = lines.get(endLine).substring(0, endColumn);
        replaceLine(lines, endLine, newLastLine);
        for (int lineno = endLine - 1; lineno > beginLine; lineno--) {
          lines.remove(lineno);
        }
        String newFirstLine = lines.get(beginLine).substring(0, beginColumn);
        replaceLine(lines, beginLine, newFirstLine);
      }
    }

    try {
      PrintWriter pw = new PrintWriter(absolutePath.toString());
      for (String line : lines) {
        pw.println(line);
      }
      pw.close();
    } catch (IOException e) {
      throw new Error(e);
    }
  }

  /**
   * If {@code newLine} is blank, removes the given line. Otherwise replaces the given line.
   *
   * @param lines the list in which to do replacement or removal
   * @param lineno the index of the line to be removed or replaced
   * @param newLine the new line for index {@code lineno}
   */
  static void replaceLine(List<String> lines, int lineno, String newLine) {
    if (isBlank(newLine)) {
      lines.remove(lineno);
    } else {
      lines.set(lineno, newLine);
    }
  }

  // TODO: Put the following utility methods in StringsPlume.

  /**
   * Returns true if the string contains only white space codepoints, otherwise false.
   *
   * <p>In Java 11, use {@code String.isBlank()} instead.
   *
   * @param s a string
   * @return true if the string contains only white space codepoints, otherwise false
   */
  static boolean isBlank(String s) {
    return s.chars().allMatch(Character::isWhitespace);
  }

  /**
   * Visits one compilation unit, collecting the annotations that should be removed. See the {@link
   * RemoveAnnotationsForInference class documentation} for more details.
   *
   * <p>The annotations will be removed from the source code by the {@link #removeAnnotations}
   * method.
   */
  private static class RemoveAnnotationsVisitor
      extends GenericListVisitorAdapter<AnnotationExpr, Void> {

    /**
     * Returns the argument if it should be removed from source code.
     *
     * @param n an annotation
     * @param superResult the result of processing the subcomponents of n
     * @return the argument to remove it, or superResult to retain it
     */
    List<AnnotationExpr> processAnnotation(AnnotationExpr n, List<AnnotationExpr> superResult) {
      if (n == null) {
        return superResult;
      }

      String name = n.getNameAsString();

      // Retain annotations defined in the JDK.
      if (isJdkAnnotation(name)) {
        return superResult;
      }
      // Retain trusted annotations.
      if (isTrustedAnnotation(name)) {
        return superResult;
      }
      // Retain annotations for which warnings are suppressed.
      if (isSuppressed(n)) {
        return superResult;
      }

      // The default behavior is to remove the annotation.
      // Don't include superResult, which is contained within `n`.
      return Collections.singletonList(n);
    }

    // There are three JavaParser AST nodes that represent annotations

    @Override
    public List<AnnotationExpr> visit(final MarkerAnnotationExpr n, final Void arg) {
      return processAnnotation(n, super.visit(n, arg));
    }

    @Override
    public List<AnnotationExpr> visit(final NormalAnnotationExpr n, final Void arg) {
      return processAnnotation(n, super.visit(n, arg));
    }

    @Override
    public List<AnnotationExpr> visit(final SingleMemberAnnotationExpr n, final Void arg) {
      return processAnnotation(n, super.visit(n, arg));
    }
  }

  /**
   * Returns true if the given annotation is defined in the JDK.
   *
   * @param name the annotation's name (simple or fully-qualified)
   * @return true if the given annotation is defined in the JDK
   */
  static boolean isJdkAnnotation(String name) {
    return name.equals("Serial")
        || name.equals("java.io.Serial")
        || name.equals("Deprecated")
        || name.equals("java.lang.Deprecated")
        || name.equals("FunctionalInterface")
        || name.equals("java.lang.FunctionalInterface")
        || name.equals("Override")
        || name.equals("java.lang.Override")
        || name.equals("SafeVarargs")
        || name.equals("java.lang.SafeVarargs")
        || name.equals("Documented")
        || name.equals("java.lang.annotation.Documented")
        || name.equals("Inherited")
        || name.equals("java.lang.annotation.Inherited")
        || name.equals("Native")
        || name.equals("java.lang.annotation.Native")
        || name.equals("Repeatable")
        || name.equals("java.lang.annotation.Repeatable")
        || name.equals("Retention")
        || name.equals("java.lang.annotation.Retention")
        || name.equals("SuppressWarnings")
        || name.equals("java.lang.SuppressWarnings")
        || name.equals("Target")
        || name.equals("java.lang.annotation.Target");
  }

  /**
   * Returns true if the given annotation is trusted, not checked/verified.
   *
   * @param name the annotation's name (simple or fully-qualified)
   * @return true if the given annotation is trusted, not verified
   */
  static boolean isTrustedAnnotation(String name) {
    // This list was determined by grepping for "trusted" in `qual` directories.
    return name.equals("Untainted")
        || name.equals("org.checkerframework.checker.tainting.qual.Untainted")
        || name.equals("InternedDistinct")
        || name.equals("org.checkerframework.checker.interning.qual.InternedDistinct")
        || name.equals("ReturnsReceiver")
        || name.equals("org.checkerframework.checker.builder.qual.ReturnsReceiver")
        || name.equals("TerminatesExecution")
        || name.equals("org.checkerframework.dataflow.qual.TerminatesExecution")
        || name.equals("Covariant")
        || name.equals("org.checkerframework.framework.qual.Covariant")
        || name.equals("NonLeaked")
        || name.equals("org.checkerframework.common.aliasing.qual.NonLeaked")
        || name.equals("LeakedToResult")
        || name.equals("org.checkerframework.common.aliasing.qual.LeakedToResult");
  }

  // This approach searches upward to find all the active warning suppressions.
  // An alternative, more efficient approach would be to track the current set of warning
  // suppressions, using a stack.
  // There are two problems with the alternative approach (and besides, this approach is fast
  // enough as it is).
  //  1. JavaParser sometimes visits members before the annotation, so there was not a chance to
  //     observe the annotation and place it on the suppression stack.  This should be fixed for
  //     ModifierVisitor (but not for other visitors such as GenericListVisitorAdapter) in
  //     JavaParser release 3.19.0.
  //  2. A user might write an annotation before @SuppressWarnings, as in:
  //       @Interned @SuppressWarnings("interning")
  //     The {@code @Interned} annotation is visited before the {@code @SuppressWarnings}
  //     annotation is.  This could be addressed by searching just the parent's annotations.

  /**
   * Returns true if warnings about the given annotation are suppressed.
   *
   * <p>Its heuristic is to look for a {@code @SuppressWarnings} annotation on a containing program
   * element, whose string is one of the elements of the annotation's fully-qualified name.
   *
   * @param arg an annotation
   * @return true if warnings about the given annotation are suppressed
   */
  private static boolean isSuppressed(AnnotationExpr arg) {
    String name = arg.getNameAsString();

    // If it's a simple name for which we know a fully-qualified name,
    // try all fully-qualified names that it could expand to.
    Collection<String> names;
    if (simpleToFullyQualified.containsKey(name)) {
      names = simpleToFullyQualified.get(name);
    } else {
      names = Collections.singletonList(name);
    }

    Iterator<Node> itor = new Node.ParentsVisitor(arg);
    while (itor.hasNext()) {
      Node n = itor.next();
      if (n instanceof NodeWithAnnotations) {
        for (AnnotationExpr ae : ((NodeWithAnnotations<?>) n).getAnnotations()) {
          if (suppresses(ae, names)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * Returns true if {@code suppressor} suppresses warnings regarding {@code suppressees}.
   *
   * @param suppressor an annotation that might be {@code @SuppressWarnings} or like it
   * @param suppressees an annotation for which warnings might be suppressed. This is actually a
   *     list: if the annotation was written unqualified, it contains all the fully-qualified names
   *     that the unqualified annotation might stand for.
   * @return true if {@code suppressor} suppresses warnings regarding {@code suppressees}
   */
  static boolean suppresses(AnnotationExpr suppressor, Collection<String> suppressees) {
    List<String> suppressWarningsStrings = suppressWarningsStrings(suppressor);
    if (suppressWarningsStrings == null) {
      return false;
    }
    List<String> checkerNames =
        CollectionsPlume.mapList(
            RemoveAnnotationsForInference::checkerName, suppressWarningsStrings);
    // "allcheckers" suppresses all warnings.
    if (checkerNames.contains("allcheckers")) {
      return true;
    }

    // Try every element of suppressee's fully-qualified name.
    for (String suppressee : suppressees) {
      for (String fqPart : suppressee.split("\\.")) {
        if (checkerNames.contains(fqPart)) {
          return true;
        }
      }
    }

    return false;
  }

  /**
   * Given a @SuppressWarnings annotation, returns its strings. Given an annotation that suppresses
   * warnings, returns strings for what it suppresses. Otherwise, returns null.
   *
   * @param n an annotation
   * @return the (effective) arguments to {@code @SuppressWarnings}, or null
   */
  private static List<String> suppressWarningsStrings(AnnotationExpr n) {
    String name = n.getNameAsString();

    if (name.equals("SuppressWarnings") || name.equals("java.lang.SuppressWarnings")) {
      if (n instanceof MarkerAnnotationExpr) {
        return Collections.emptyList();
      } else if (n instanceof NormalAnnotationExpr) {
        NodeList<MemberValuePair> pairs = ((NormalAnnotationExpr) n).getPairs();
        assert pairs.size() == 1;
        MemberValuePair pair = pairs.get(0);
        assert pair.getName().asString().equals("value");
        return annotationElementStrings(pair.getValue());
      } else if (n instanceof SingleMemberAnnotationExpr) {
        return annotationElementStrings(((SingleMemberAnnotationExpr) n).getMemberValue());
      } else {
        throw new BugInCF("Unexpected AnnotationExpr of type %s: %s", n.getClass(), n);
      }
    }

    if (name.equals("IgnoreInWholeProgramInference")
        || name.equals("org.checkerframework.framework.qual.IgnoreInWholeProgramInference")
        || name.equals("Inject")
        || name.equals("javax.inject.Inject")
        || name.equals("Singleton")
        || name.equals("javax.inject.Singleton")
        || name.equals("Option")
        || name.equals("org.plumelib.options.Option")) {
      return Collections.singletonList("allcheckers");
    }

    return null;
  }

  /**
   * Given an annotation argument for an element of type String[], return a list of strings.
   *
   * @param e an annotation argument
   * @return the strings expressed by {@code e}
   */
  private static List<String> annotationElementStrings(Expression e) {
    if (e instanceof StringLiteralExpr) {
      return Collections.singletonList(((StringLiteralExpr) e).asString());
    } else if (e instanceof ArrayInitializerExpr) {
      NodeList<Expression> values = ((ArrayInitializerExpr) e).getValues();
      List<String> result = new ArrayList<>(values.size());
      for (Expression v : values) {
        if (v instanceof StringLiteralExpr) {
          result.add(((StringLiteralExpr) v).asString());
        } else {
          throw new BugInCF("Unexpected annotation element of type %s: %s", v.getClass(), v);
        }
      }
      return result;
    } else {
      throw new BugInCF("Unexpected %s: %s", e.getClass(), e);
    }
  }

  /**
   * Returns the "checker name" part of a SuppressWarnings string: the part before the colon, or the
   * whole thing if it contains no colon.
   *
   * @param s a SuppressWarnings string: the argument to {@code @SuppressWarnings}
   * @return the part of s before the colon, or the whole thing if it contains no colon
   */
  private static String checkerName(String s) {
    int colonPos = s.indexOf(":");
    if (colonPos == -1) {
      return s;
    } else {
      return s.substring(colonPos + 1);
    }
  }
}
