Skip to content

Commit

Permalink
Add basic support for grouping results by severity (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
jshiell committed Nov 18, 2024
1 parent 154d105 commit 618bc50
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 136 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# CheckStyle-IDEA Changelog

* **5.99.0** New: Added option to group results by package (#3).
* **5.99.0** New: Added option to group results by package and severity (#3).
* **5.98.0** New: Added Checkstyle 10.20.1.
* **5.97.0** Fixed: Refactored code to fix exception around API dependencies at initialisation (#655).
* **5.97.0** New: Added Checkstyle 10.19.0.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.infernus.idea.checkstyle.actions;

import org.infernus.idea.checkstyle.toolwindow.ResultGrouping;

public class GroupBySeverity extends GroupingAction {

public GroupBySeverity() {
super(ResultGrouping.BY_SEVERITY);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.infernus.idea.checkstyle.toolwindow;

import com.intellij.icons.AllIcons;

public class FileGroupTreeInfo extends GroupTreeInfo {

/**
* Construct a file node.
*
* @param fileName the name of the file.
* @param problemCount the number of problems in the file.
*/
public FileGroupTreeInfo(final String fileName, final int problemCount) {
super(fileName, "file", AllIcons.FileTypes.Java, problemCount);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.infernus.idea.checkstyle.toolwindow;

import org.infernus.idea.checkstyle.CheckStyleBundle;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;

abstract class GroupTreeInfo extends ResultTreeNode {

private final String name;
private final String groupId;
private final int totalProblems;
private int visibleProblems;

/**
* Construct a group node.
*
* @param name the name of the group.
* @param groupId the ID used as part of message lookup.
* @param icon the icon of the group.
* @param problemCount the number of problems in the group.
*/
public GroupTreeInfo(@NotNull final String name,
@NotNull final String groupId,
@NotNull final Icon icon,
final int problemCount) {
super(CheckStyleBundle.message("plugin.results.scan-" + groupId + "-result", name, problemCount));

this.name = name;
this.groupId = groupId;
this.totalProblems = problemCount;
this.visibleProblems = problemCount;

updateDisplayText();
setIcon(icon);
}

private void updateDisplayText() {
if (totalProblems == visibleProblems) {
setText(CheckStyleBundle.message("plugin.results.scan-" + groupId + "-result", name, totalProblems));
} else {
setText(CheckStyleBundle.message("plugin.results.scan-" + groupId + "-result.filtered", name, visibleProblems, totalProblems - visibleProblems));
}
}

void setVisibleProblems(final int visibleProblems) {
this.visibleProblems = visibleProblems;

updateDisplayText();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.infernus.idea.checkstyle.toolwindow;

import com.intellij.icons.AllIcons;

public class PackageGroupTreeInfo extends GroupTreeInfo {

/**
* Construct a package node.
*
* @param packageName the name of the package.
* @param problemCount the number of problems in the file.
*/
public PackageGroupTreeInfo(final String packageName, final int problemCount) {
super(packageName, "package", AllIcons.Nodes.Package, problemCount);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
public enum ResultGrouping {

BY_FILE,
BY_PACKAGE
BY_PACKAGE,
BY_SEVERITY

}
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ private void rebuildTree() {
visibleRootNode.removeAllChildren();

switch (grouping) {
case BY_FILE -> groupResultsByFile();
case BY_PACKAGE -> groupResultsByPackage();
case BY_SEVERITY -> groupResultsBySeverity();
default -> groupResultsByFile();
}

filterDisplayedTree();
Expand Down Expand Up @@ -125,12 +126,8 @@ private void filterNodeAndChildren(final ToggleableTreeNode node) {
filterNodeAndChildren(childNode);
}

if (node.getUserObject() instanceof FileResultTreeInfo fileResultTreeInfo) {
fileResultTreeInfo.setVisibleProblems(node.getChildCount());
nodeShouldBeVisible = node.getChildCount() > 0;

} else if (node.getUserObject() instanceof PackageTreeInfo packageTreeInfo) {
packageTreeInfo.setVisibleProblems(node.getChildCount());
if (node.getUserObject() instanceof GroupTreeInfo groupTreeInfo) {
groupTreeInfo.setVisibleProblems(node.getChildCount());
nodeShouldBeVisible = node.getChildCount() > 0;

} else if (node.getUserObject() instanceof ProblemResultTreeInfo problemResultTreeInfo) {
Expand Down Expand Up @@ -166,10 +163,40 @@ public void setModel(@NotNull final Map<PsiFile, List<Problem>> results,
}

private void groupResultsByFile() {
int problemCount = createFileNodes(sortByFileName(lastResults), visibleRootNode);
int problemCount = createFileNodes(sortByFileName(lastResults), lastResults, visibleRootNode);
setRootMessage(problemCount);
}

private int createFileNodes(final List<PsiFile> sortedFiles,
final Map<PsiFile, List<Problem>> problemsForAllFiles,
final ToggleableTreeNode parentNode) {
int problemCount = 0;
for (final PsiFile file : sortedFiles) {
final var fileNode = new ToggleableTreeNode();
final var problems = problemsForAllFiles.getOrDefault(file, emptyList());

int childProblemCount = 0;
for (final Problem problem : problems) {
if (problem.severityLevel() != SeverityLevel.Ignore) {
final var problemInfo = new ProblemResultTreeInfo(file, problem);
fileNode.add(new ToggleableTreeNode(problemInfo));

++childProblemCount;
}
}

if (childProblemCount > 0) {
var nodeObject = new FileGroupTreeInfo(file.getName(), childProblemCount);
fileNode.setUserObject(nodeObject);

parentNode.add(fileNode);
}

problemCount += childProblemCount;
}
return problemCount;
}

private List<PsiFile> sortByFileName(final Map<PsiFile, List<Problem>> results) {
if (results == null || results.isEmpty()) {
return emptyList();
Expand All @@ -186,9 +213,9 @@ private void groupResultsByPackage() {
for (String packageName : groupedByPackage.keySet()) {
final var packageNode = new ToggleableTreeNode();

var childProblemCount = createFileNodes(groupedByPackage.getOrDefault(packageName, emptyList()), packageNode);
var childProblemCount = createFileNodes(groupedByPackage.getOrDefault(packageName, emptyList()), lastResults, packageNode);
if (childProblemCount > 0) {
final var packageInfo = new PackageTreeInfo(packageName, childProblemCount);
final var packageInfo = new PackageGroupTreeInfo(packageName, childProblemCount);
packageNode.setUserObject(packageInfo);
visibleRootNode.add(packageNode);
}
Expand All @@ -199,35 +226,6 @@ private void groupResultsByPackage() {
setRootMessage(problemCount);
}

private int createFileNodes(final List<PsiFile> files,
final ToggleableTreeNode parentNode) {
int problemCount = 0;
for (final PsiFile file : files) {
final var fileNode = new ToggleableTreeNode();
final var problems = lastResults.getOrDefault(file, emptyList());

int childProblemCount = 0;
for (final Problem problem : problems) {
if (problem.severityLevel() != SeverityLevel.Ignore) {
final var problemInfo = new ProblemResultTreeInfo(file, problem);
fileNode.add(new ToggleableTreeNode(problemInfo));

++childProblemCount;
}
}

if (childProblemCount > 0) {
var nodeObject = new FileResultTreeInfo(file.getName(), childProblemCount);
fileNode.setUserObject(nodeObject);

parentNode.add(fileNode);
}

problemCount += childProblemCount;
}
return problemCount;
}

private SortedMap<String, List<PsiFile>> groupByPackageName(final Map<PsiFile, List<Problem>> results) {
if (results == null || results.isEmpty()) {
return Collections.emptySortedMap();
Expand All @@ -247,6 +245,48 @@ private SortedMap<String, List<PsiFile>> groupByPackageName(final Map<PsiFile, L
return groupedByPackage;
}

private void groupResultsBySeverity() {
int problemCount = 0;

var groupedBySeverity = groupBySeverity(lastResults);
for (SeverityLevel severityLevel : groupedBySeverity.keySet()) {
final var severityNode = new ToggleableTreeNode();

var fileToProblems = groupedBySeverity.get(severityLevel);
var childProblemCount = createFileNodes(sortByFileName(fileToProblems), fileToProblems, severityNode);
if (childProblemCount > 0) {
final var packageInfo = new SeverityGroupTreeInfo(severityLevel, childProblemCount);
severityNode.setUserObject(packageInfo);
visibleRootNode.add(severityNode);
}

problemCount += childProblemCount;
}

setRootMessage(problemCount);
}

private SortedMap<SeverityLevel, Map<PsiFile, List<Problem>>> groupBySeverity(final Map<PsiFile, List<Problem>> results) {
if (results == null || results.isEmpty()) {
return Collections.emptySortedMap();
}
var severities = List.of(SeverityLevel.Error, SeverityLevel.Warning, SeverityLevel.Info);

var groupedBySeverity = new TreeMap<SeverityLevel, Map<PsiFile, List<Problem>>>();
severities.forEach(severityLevel -> groupedBySeverity.put(severityLevel, new HashMap<>()));

for (var resultFile : results.keySet()) {
var problems = results.get(resultFile);

for (SeverityLevel severityLevel : severities) {
groupedBySeverity.get(severityLevel).put(
resultFile,
problems.stream().filter(item -> item.severityLevel() == severityLevel).toList());
}
}
return groupedBySeverity;
}

private void setRootMessage(final int problemCount) {
if (problemCount == 0) {
setRootMessage("plugin.results.scan-no-results");
Expand Down
Loading

0 comments on commit 618bc50

Please sign in to comment.