package org.intellij.sonar.analysis; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.intellij.codeInspection.GlobalInspectionContext; import com.intellij.codeInspection.InspectionEP; import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.ProblemDescriptionsProcessor; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiFile; import org.intellij.sonar.index.SonarIssue; import org.intellij.sonar.persistence.IssuesByFileIndexProjectComponent; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class NewIssuesGlobalInspectionTool extends BaseGlobalInspectionTool { private static final String SONAR_QUBE = "SonarQube"; /** @see InspectionEP#groupDisplayName @see InspectionEP#groupKey @see InspectionEP#groupBundle */ @Nls @NotNull @Override public String getGroupDisplayName() { return "SonarQube (new issues)"; } /** Override this method to return a html inspection description. Otherwise it will be loaded from resources using ID. @return hard-code inspection description. */ @Nullable @Override public String getStaticDescription() { return "Reports new issues found by SonarQube."; } @Override public Boolean processIssue(SonarIssue issue) { return issue.getIsNew(); } @Override public void inspectionFinished( @NotNull InspectionManager manager, @NotNull GlobalInspectionContext context, @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor ) { super.inspectionFinished(manager,context,problemDescriptionsProcessor); final ImmutableList.Builder<PsiFile> pfb = ImmutableList.builder(); context.getRefManager().getScope().accept( new PsiElementVisitor() { @Override public void visitFile(PsiFile file) { pfb.add(file); } } ); final ImmutableList<PsiFile> analyzedFiles = pfb.build(); final Set<String> analyzedPaths = analyzedFiles.stream() .filter(Objects::nonNull) .map(psiFile -> psiFile.getVirtualFile().getPath()) .collect(Collectors.toSet()); final Optional<IssuesByFileIndexProjectComponent> indexComponent = IssuesByFileIndexProjectComponent.getInstance(context.getProject()); if (indexComponent.isPresent()) { final int newIssuesCount = FluentIterable.from(indexComponent.get().getIndex().entrySet()) .filter( entry -> analyzedPaths.contains(entry.getKey()) ) .transformAndConcat( entry -> entry.getValue() ) .filter( sonarIssue -> sonarIssue.getIsNew() ).size(); final Notification notification; if (newIssuesCount == 1) { notification = new Notification( SONAR_QUBE,SONAR_QUBE, "Found 1 new SonarQube issue", NotificationType.WARNING ); } else if (newIssuesCount > 1) { notification = new Notification( SONAR_QUBE,SONAR_QUBE, String.format("Found %d new SonarQube issues",newIssuesCount), NotificationType.WARNING ); } else { notification = new Notification( SONAR_QUBE,SONAR_QUBE, "No new SonarQube issues", NotificationType.INFORMATION ); } Notifications.Bus.notify(notification,context.getProject()); } } }