All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.bjurr.violations.comments.lib.CommentsCreator Maven / Gradle / Ivy

There is a newer version: 1.109.0
Show newest version
package se.bjurr.violations.comments.lib;

import static java.util.logging.Level.INFO;
import static java.util.stream.Collectors.joining;
import static se.bjurr.violations.comments.lib.ChangedFileUtils.findChangedFile;
import static se.bjurr.violations.comments.lib.CommentFilterer.filterCommentsWithContent;
import static se.bjurr.violations.comments.lib.CommentFilterer.filterCommentsWithoutContent;
import static se.bjurr.violations.comments.lib.CommentFilterer.getViolationComments;
import static se.bjurr.violations.comments.lib.ViolationRenderer.createSingleFileCommentContent;
import static se.bjurr.violations.comments.lib.ViolationRenderer.getAccumulatedComments;
import static se.bjurr.violations.lib.util.Utils.checkNotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import se.bjurr.violations.comments.lib.model.ChangedFile;
import se.bjurr.violations.comments.lib.model.Comment;
import se.bjurr.violations.lib.ViolationsLogger;
import se.bjurr.violations.lib.model.Violation;

public class CommentsCreator {
  public static final String FINGERPRINT =
      "";
  public static final String FINGERPRINT_ACC = "";
  private final ViolationsLogger violationsLogger;
  private final CommentsProvider commentsProvider;
  private final List files;
  private final Set violations;

  public static void createComments(
      final ViolationsLogger violationsLogger,
      final Set violations,
      final CommentsProvider commentsProvider) {

    final CommentsCreator commentsCreator =
        new CommentsCreator(violationsLogger, commentsProvider, violations);
    commentsCreator.createComments();
  }

  CommentsCreator(
      final ViolationsLogger violationsLogger,
      final CommentsProvider commentsProvider,
      final Set violations) {
    checkNotNull(violations, "violations");
    checkNotNull(commentsProvider, "commentsProvider");
    this.violationsLogger = checkNotNull(violationsLogger, "violationsLogger");
    this.commentsProvider = commentsProvider;
    this.files = commentsProvider.getFiles();
    Set allViolations = violations;
    if (commentsProvider.shouldCommentOnlyChangedFiles()) {
      allViolations = this.filterChanged(this.files, violations);
      this.violationsLogger.log(
          Level.INFO,
          "Found "
              + this.files.size()
              + " changed files with "
              + allViolations.size()
              + " violations");
    }
    if (commentsProvider.getMaxNumberOfViolations() != null
        && allViolations.size() > commentsProvider.getMaxNumberOfViolations()) {
      final List list = new ArrayList<>(allViolations);
      final List subList = list.subList(0, commentsProvider.getMaxNumberOfViolations());
      this.violations = new TreeSet<>(subList);
      this.violationsLogger.log(
          Level.INFO,
          "Reducing violations " + allViolations.size() + " to " + this.violations.size());
    } else {
      this.violations = allViolations;
    }
  }

  public void createComments() {
    if (this.commentsProvider.shouldCreateCommentWithAllSingleFileComments()) {
      this.createCommentWithAllSingleFileComments();
    }
    if (this.commentsProvider.shouldCreateSingleFileComment()) {
      if (!this.commentsProvider.shouldCommentOnlyChangedFiles()) {
        throw new IllegalStateException(
            "Cannot comment single files when having commentOnlyChangedFiles set to false");
      }
      this.createSingleFileComments();
    }
    if (!this.commentsProvider.shouldCreateCommentWithAllSingleFileComments()
        && !this.commentsProvider.shouldCreateSingleFileComment()) {
      this.violationsLogger.log(
          INFO,
          "Will not comment because both 'CreateCommentWithAllSingleFileComments' and 'CreateSingleFileComment' is false.");
    }
  }

  private void createCommentWithAllSingleFileComments() {
    final List accumulatedComments =
        getAccumulatedComments(
            this.violations,
            this.files,
            this.commentsProvider.findCommentTemplate().orElse(null),
            this.commentsProvider.getMaxCommentSize());
    for (final String accumulatedComment : accumulatedComments) {
      this.violationsLogger.log(
          INFO,
          "Asking "
              + this.commentsProvider.getClass().getSimpleName()
              + " to create comment with all single file comments.");
      List oldComments = this.commentsProvider.getComments();
      oldComments = filterCommentsWithContent(oldComments, FINGERPRINT_ACC);
      final List alreadyMadeComments =
          filterCommentsWithContent(oldComments, accumulatedComment);

      this.removeOldCommentsThatAreNotStillReported(oldComments, alreadyMadeComments);

      if (this.violations.isEmpty()) {
        this.violationsLogger.log(Level.INFO, "No violations to comment");
        return;
      }

      final boolean commentHasNotBeenMade = alreadyMadeComments.isEmpty();
      if (commentHasNotBeenMade) {
        this.commentsProvider.createComment(accumulatedComment);
      }
    }
  }

  private void createSingleFileComments() {
    List oldComments = this.commentsProvider.getComments();
    oldComments = filterCommentsWithContent(oldComments, FINGERPRINT);
    oldComments = filterCommentsWithoutContent(oldComments, FINGERPRINT_ACC);
    this.violationsLogger.log(
        INFO, "Asking " + this.commentsProvider.getClass().getSimpleName() + " to comment:");

    final ViolationComments alreadyMadeComments =
        getViolationComments(oldComments, this.violations);

    this.removeOldCommentsThatAreNotStillReported(oldComments, alreadyMadeComments.getComments());

    for (final Violation violation : this.violations) {
      final boolean violationCommentExistsSinceBefore =
          alreadyMadeComments.getViolations().contains(violation);
      if (violationCommentExistsSinceBefore) {
        continue;
      }
      final Optional changedFile = findChangedFile(this.files, violation);
      if (changedFile.isPresent()) {
        final String commentTemplate = this.commentsProvider.findCommentTemplate().orElse(null);
        final String singleFileCommentContent =
            createSingleFileCommentContent(changedFile.get(), violation, commentTemplate);
        this.violationsLogger.log(
            INFO,
            violation.getReporter()
                + " "
                + violation.getSeverity()
                + " "
                + violation.getRule()
                + " "
                + changedFile.get().getFilename()
                + " "
                + violation.getStartLine()
                + " "
                + violation.getSource());
        this.commentsProvider.createSingleFileComment(
            changedFile.get(), violation.getStartLine(), singleFileCommentContent);
      }
    }
  }

  private void removeOldCommentsThatAreNotStillReported(
      final List oldComments, final List comments) {
    if (!this.commentsProvider.shouldKeepOldComments()) {
      final List existingWithoutViolation = new ArrayList<>();
      existingWithoutViolation.addAll(oldComments);
      existingWithoutViolation.removeAll(comments);
      this.commentsProvider.removeComments(existingWithoutViolation);
    }
  }

  private Set filterChanged(
      final List files, final Set mixedViolations) {
    final String changedFiles =
        files //
            .stream() //
            .map((f) -> f.getFilename()) //
            .sorted() //
            .collect(joining("\n  "));
    this.violationsLogger.log(INFO, "Files changed:\n  " + changedFiles);

    final String violationFiles =
        mixedViolations //
            .stream() //
            .map((f) -> f.getFile()) //
            .distinct() //
            .sorted() //
            .collect(joining("\n  "));
    this.violationsLogger.log(INFO, "Files with violations:\n  " + violationFiles);

    final Set isChanged = new TreeSet<>();
    final Set included = new TreeSet<>();
    final Set notIncludedUntouched = new TreeSet<>();
    final Set notIncludedNotChanged = new TreeSet<>();
    for (final Violation violation : mixedViolations) {
      final Optional file = findChangedFile(files, violation);
      final String violationFile = violation.getFile() + " " + violation.getStartLine();
      if (file.isPresent()) {
        final boolean shouldComment =
            this.commentsProvider.shouldComment(file.get(), violation.getStartLine());
        if (shouldComment) {
          isChanged.add(violation);
          included.add(violationFile);
        } else {
          notIncludedUntouched.add(violationFile);
        }
      } else {
        notIncludedNotChanged.add(violationFile);
      }
    }

    if (!included.isEmpty()) {
      this.violationsLogger.log(
          INFO, "Will include violations on:\n  " + included.stream().collect(joining("\n  ")));
    }

    if (!notIncludedUntouched.isEmpty()) {
      this.violationsLogger.log(
          INFO,
          "Will not include violations on changed files because violation reported on untouched lines:\n  "
              + notIncludedUntouched.stream().collect(joining("\n  ")));
    }

    if (!notIncludedNotChanged.isEmpty()) {
      this.violationsLogger.log(
          INFO,
          "Will not include violations on unchanged files:\n  "
              + notIncludedNotChanged.stream().collect(joining("\n  ")));
    }

    return isChanged;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy