From 7f85d15e81284a267c62a100ad36c6aac4c16dd9 Mon Sep 17 00:00:00 2001 From: nanguoqiang Date: Tue, 14 Mar 2023 18:05:22 +0800 Subject: [PATCH] Release 0.2.3 --- README.md | 7 +- README.zh-CN.md | 7 +- build.gradle | 2 +- .../plugin/sonar/core/LogOutputImpl.java | 6 + .../intellij/plugin/sonar/core/Report.java | 43 ++++++++ .../toolwindow/IssuesDisplayControlPanel.java | 32 +++++- .../sonar/gui/toolwindow/IssuesPanel.java | 9 +- .../sonar/gui/toolwindow/SearchPanel.java | 77 +++++++++++++ .../sonar/service/ProblemCacheService.java | 103 ++++++++++++++++-- src/main/resources/META-INF/plugin.xml | 6 + src/main/resources/i18n/Messages.properties | 8 +- .../resources/i18n/Messages_en.properties | 8 +- 12 files changed, 294 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/SearchPanel.java diff --git a/README.md b/README.md index 6a521d1..c55163c 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,12 @@ You can filter the issues by the following categories: * Resolution * Resolved * Unresolved - +* Severity + * Blocker + * Critical + * Major + * Minor + * Info ## Contributing diff --git a/README.zh-CN.md b/README.zh-CN.md index 8beb34f..70db690 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -133,7 +133,12 @@ Project级别设置主要包含: * 解决 * 已解决 * 未解决 - +* 严重程度 + * 阻断 + * 严重 + * 主要 + * 次要 + * 提示 ## 如何贡献 diff --git a/build.gradle b/build.gradle index a00dd0d..e90e789 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'org.jetbrains.intellij' apply plugin: 'java' group 'com.yujunyang' -version '0.2.2' +version '0.2.3' sourceCompatibility = 1.8 diff --git a/src/main/java/com/yujunyang/intellij/plugin/sonar/core/LogOutputImpl.java b/src/main/java/com/yujunyang/intellij/plugin/sonar/core/LogOutputImpl.java index 3a17c6a..3e672ae 100644 --- a/src/main/java/com/yujunyang/intellij/plugin/sonar/core/LogOutputImpl.java +++ b/src/main/java/com/yujunyang/intellij/plugin/sonar/core/LogOutputImpl.java @@ -72,6 +72,12 @@ public void log(String formattedMessage, Level level) { report.getVulnerabilityCount(), report.getDuplicatedBlocksCount(), report.getSecurityHotSpotCount()); + problemCacheService.setSeverityStats( + report.getBlockerCount(), + report.getCriticalCount(), + report.getMajorCount(), + report.getMinorCount(), + report.getInfoCount()); return report; }); diff --git a/src/main/java/com/yujunyang/intellij/plugin/sonar/core/Report.java b/src/main/java/com/yujunyang/intellij/plugin/sonar/core/Report.java index 2d352ca..34d48f6 100644 --- a/src/main/java/com/yujunyang/intellij/plugin/sonar/core/Report.java +++ b/src/main/java/com/yujunyang/intellij/plugin/sonar/core/Report.java @@ -61,6 +61,8 @@ public class Report { private CopyOnWriteArraySet ignoreRules; private int ignoreIssueCount; + private int blockerCount, criticalCount, majorCount, minorCount, infoCount; + public Report(@NotNull Project project, @NotNull File reportDir) { this.project = project; this.reportDir = reportDir; @@ -157,6 +159,26 @@ private void analyze() { break; } + switch (reportIssue.getSeverity()) { + case BLOCKER: + blockerCount++; + break; + case CRITICAL: + criticalCount++; + break; + case MAJOR: + majorCount++; + break; + case MINOR: + minorCount++; + break; + case INFO: + infoCount++; + break; + default: + //do nothing + } + if (ignoreIssue) { ignoreRules.add(issueRuleKey); MessageBusManager.publishLogToEDT(project, String.format("Rule[%s] type[%s] 暂未被报告解析程序支持, 展示的报告中将忽略此类型相关问题, 在后续插件更新中可能会增加支持", issueRuleKey, rule.getType()), LogOutput.Level.ERROR); @@ -296,4 +318,25 @@ private List getRules() { // } // return rule; } + + public int getBlockerCount() { + return blockerCount; + } + + public int getCriticalCount() { + return criticalCount; + } + + public int getMajorCount() { + return majorCount; + } + + public int getMinorCount() { + return minorCount; + } + + public int getInfoCount() { + return infoCount; + } + } diff --git a/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/IssuesDisplayControlPanel.java b/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/IssuesDisplayControlPanel.java index a161b8f..42d5c1e 100644 --- a/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/IssuesDisplayControlPanel.java +++ b/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/IssuesDisplayControlPanel.java @@ -54,6 +54,11 @@ public class IssuesDisplayControlPanel extends JBPanel { private JBLabel unresolvedCountLabel; private JBLabel updatedFilesCountLabel; private JBLabel notUpdatedFilesCountLabel; + private JBLabel blockerCountLabel; + private JBLabel criticalCountLabel; + private JBLabel majorCountLabel; + private JBLabel minorCountLabel; + private JBLabel infoCountLabel; public IssuesDisplayControlPanel(Project project) { this.project = project; @@ -64,6 +69,19 @@ public IssuesDisplayControlPanel(Project project) { private void init() { setLayout(new SampleVerticalScrollLayout()); + add(Box.createVerticalStrut(5)); + addTitleLabel(ResourcesLoader.getString("toolWindow.report.displayControl.severityTitle")); + blockerCountLabel = createCountLabel("0"); + addControlItemPanel("severity.blocker", blockerCountLabel, "BLOCKER"); + criticalCountLabel = createCountLabel("0"); + addControlItemPanel("severity.critical", criticalCountLabel, "CRITICAL"); + majorCountLabel = createCountLabel("0"); + addControlItemPanel("severity.major", majorCountLabel, "MAJOR"); + minorCountLabel = createCountLabel("0"); + addControlItemPanel("severity.minor", minorCountLabel, "MINOR"); + infoCountLabel = createCountLabel("0"); + addControlItemPanel("severity.info", infoCountLabel, "INFO"); + addTitleLabel(ResourcesLoader.getString("toolWindow.report.displayControl.issueTypeTitle")); bugCountLabel = createCountLabel("0"); addControlItemPanel("issueType.bug", bugCountLabel, "BUG"); @@ -104,6 +122,13 @@ public void refresh() { notUpdatedFilesCountLabel.setText(String.valueOf(problemCacheService.getNotUpdatedFilesIssueCount())); resolvedCountLabel.setText(String.valueOf(problemCacheService.getFixedIssueCount())); unresolvedCountLabel.setText(String.valueOf(problemCacheService.getUnresolvedIssueCount())); + + blockerCountLabel.setText(String.valueOf(problemCacheService.getUnresolvedIssueCount())); + blockerCountLabel.setText(String.valueOf(problemCacheService.getBlockerCount())); + criticalCountLabel.setText(String.valueOf(problemCacheService.getCriticalCount())); + majorCountLabel.setText(String.valueOf(problemCacheService.getMajorCount())); + minorCountLabel.setText(String.valueOf(problemCacheService.getMinorCount())); + infoCountLabel.setText(String.valueOf(problemCacheService.getInfoCount())); } public void reset() { @@ -116,7 +141,12 @@ public void reset() { updatedFilesCountLabel, notUpdatedFilesCountLabel, resolvedCountLabel, - unresolvedCountLabel).forEach(label -> { + unresolvedCountLabel, + blockerCountLabel, + criticalCountLabel, + majorCountLabel, + minorCountLabel, + infoCountLabel).forEach(label -> { label.setText("0"); cancelHighlight((JBPanel)(label.getParent())); }); diff --git a/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/IssuesPanel.java b/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/IssuesPanel.java index 7c9ae0d..16dd78a 100644 --- a/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/IssuesPanel.java +++ b/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/IssuesPanel.java @@ -47,6 +47,7 @@ public class IssuesPanel extends JBPanel { private IssuesDisplayControlPanel issuesDisplayControlPanel; private JBPanel listPanelParent; private CardLayout listPanelParentLayout; + private SearchPanel searchPanel; public IssuesPanel(Project project) { this.project = project; @@ -58,6 +59,9 @@ private void init() { setLayout(new BorderLayout()); setSize(300, 300); + searchPanel = new SearchPanel(project); + add(searchPanel, BorderLayout.NORTH); + displayControlScrollPane = new JBScrollPane(); displayControlScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); displayControlScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -112,8 +116,10 @@ public void refresh() { private void filter() { listScrollPane.getVerticalScrollBar().setValue(0); + ProblemCacheService problemCacheService = ProblemCacheService.getInstance(project); + problemCacheService.doFilterIssues(); issueListPanel.refresh(); - if (ProblemCacheService.getInstance(project).getFilteredIssues().size() > 0) { + if (problemCacheService.getFilteredIssues().size() > 0) { listPanelParentLayout.show(listPanelParent, "ISSUES_LIST"); } else { listPanelParentLayout.show(listPanelParent, "ISSUES_EMPTY"); @@ -125,5 +131,6 @@ private void filter() { public void reset() { issuesDisplayControlPanel.reset(); issueListPanel.reset(); + searchPanel.reset(); } } diff --git a/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/SearchPanel.java b/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/SearchPanel.java new file mode 100644 index 0000000..cc9195f --- /dev/null +++ b/src/main/java/com/yujunyang/intellij/plugin/sonar/gui/toolwindow/SearchPanel.java @@ -0,0 +1,77 @@ +package com.yujunyang.intellij.plugin.sonar.gui.toolwindow; + +import com.google.common.base.Splitter; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.project.Project; +import com.intellij.ui.components.JBBox; +import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBPanel; +import com.intellij.ui.components.JBTextField; +import com.intellij.util.ui.JBUI; +import com.yujunyang.intellij.plugin.sonar.messages.MessageBusManager; +import com.yujunyang.intellij.plugin.sonar.service.ProblemCacheService; +import org.apache.commons.lang3.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.Set; + +public class SearchPanel extends JBPanel { + + private final Project project; + + private JBTextField searchField; + + private JButton searchButton; + + public SearchPanel(Project project) { + this.project = project; + setLayout(new BorderLayout()); + init(); + } + + private void init() { + JBBox horizontalBox = JBBox.createHorizontalBox(); + horizontalBox.setBorder(JBUI.Borders.empty(2, 5)); + + horizontalBox.add(new JBLabel("RuleKey: ")); + + searchField = new JBTextField(""); + searchField.getEmptyText().setText("Example:S112 S3518"); + horizontalBox.add(searchField); + + searchButton = new JButton(AllIcons.Actions.Search); + horizontalBox.add(searchButton); + + searchField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + searchButton.doClick(); + } + } + }); + + searchButton.addActionListener(actionEvent -> { + Set ruleKeys = ProblemCacheService.getInstance(project).getRuleKeys(); + ruleKeys.clear(); + String ruleKey = searchField.getText(); + if (StringUtils.isNoneBlank(ruleKey)) { + Splitter.on(" ") + .omitEmptyStrings() + .trimResults() + .split(ruleKey.toUpperCase()) + .forEach(ruleKeys::add); + } + MessageBusManager.publishIssueFilter(project); + }); + + add(horizontalBox, BorderLayout.CENTER); + } + + public void reset() { + searchField.setText(""); + } +} diff --git a/src/main/java/com/yujunyang/intellij/plugin/sonar/service/ProblemCacheService.java b/src/main/java/com/yujunyang/intellij/plugin/sonar/service/ProblemCacheService.java index 0ba7926..3386ca1 100644 --- a/src/main/java/com/yujunyang/intellij/plugin/sonar/service/ProblemCacheService.java +++ b/src/main/java/com/yujunyang/intellij/plugin/sonar/service/ProblemCacheService.java @@ -37,6 +37,7 @@ import com.yujunyang.intellij.plugin.sonar.core.AnalyzeScope; import com.yujunyang.intellij.plugin.sonar.core.DuplicatedBlocksIssue; import com.yujunyang.intellij.plugin.sonar.core.Issue; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; public class ProblemCacheService { @@ -58,6 +59,12 @@ public class ProblemCacheService { private AnalyzeScope analyzeScope; + private Set ruleKeys; + + private ConcurrentMap> filteredIssues; + + private int blockerCount, criticalCount, majorCount, minorCount, infoCount; + public ProblemCacheService(Project project) { this.project = project; issues = new ConcurrentHashMap<>(); @@ -72,15 +79,18 @@ public ProblemCacheService(Project project) { ignoreIssueCount = 0; filters = new HashSet<>(); + ruleKeys = new HashSet<>(); + filteredIssues = new ConcurrentHashMap<>(); } public ConcurrentMap> getIssues() { return issues; } - public ConcurrentMap> getFilteredIssues() { - if (filters.size() == 0) { - return issues; + public void doFilterIssues() { + filteredIssues.clear(); + if (!isFilter()) { + return; } boolean includeBug = filters.contains("BUG"); @@ -95,10 +105,15 @@ public ConcurrentMap> getFilteredIssues() { boolean includeResolved = filters.contains("RESOLVED"); boolean includeUnresolved = filters.contains("UNRESOLVED"); boolean filterByStatus = includeResolved || includeUnresolved; + boolean includeBlocker = filters.contains("BLOCKER"); + boolean includeCritical = filters.contains("CRITICAL"); + boolean includeMajor = filters.contains("MAJOR"); + boolean includeMinor = filters.contains("MINOR"); + boolean includeInfo = filters.contains("INFO"); + boolean filterBySeverity = includeBlocker || includeCritical || includeMajor || includeMinor || includeInfo; List changedFiles = GitService.getInstance(project).getChangedFiles(); - ConcurrentMap> ret = new ConcurrentHashMap<>(); issues.forEach((psiFile, issues) -> { List retIssues = new ArrayList<>(); for (AbstractIssue issue : issues) { @@ -158,17 +173,39 @@ public ConcurrentMap> getFilteredIssues() { } } + if (filterBySeverity) { + include = false; + + if (includeBlocker && StringUtils.equalsIgnoreCase(issue.getSeverity(), "BLOCKER")) { + include = true; + } else if (includeCritical && StringUtils.equalsIgnoreCase(issue.getSeverity(), "CRITICAL")) { + include = true; + } else if (includeMajor && StringUtils.equalsIgnoreCase(issue.getSeverity(), "MAJOR")) { + include = true; + } else if (includeMinor && StringUtils.equalsIgnoreCase(issue.getSeverity(), "MINOR")) { + include = true; + } else if (includeInfo && StringUtils.equalsIgnoreCase(issue.getSeverity(), "INFO")) { + include = true; + } + + if (!include) { + continue; + } + } + + if (!ruleKeys.isEmpty()) { + include = ruleKeys.contains(issue.getRuleKey()); + } + if (include) { retIssues.add(issue); } } if (retIssues.size() > 0) { - ret.put(psiFile, retIssues); + filteredIssues.put(psiFile, retIssues); } }); - - return ret; } public void setIssues(ConcurrentMap> issues) { @@ -220,6 +257,14 @@ public void setStats(int bugCount, int codeSmellCount, int vulnerabilityCount, i this.securityHotSpotCount = securityHotSpotCount; } + public void setSeverityStats(int blockerCount, int criticalCount, int majorCount, int minorCount, int infoCount) { + this.blockerCount = blockerCount; + this.criticalCount = criticalCount; + this.majorCount = majorCount; + this.minorCount = minorCount; + this.infoCount = infoCount; + } + public boolean isInitialized() { return initialized; } @@ -241,11 +286,18 @@ public void reset() { duplicatedBlocksCount = 0; securityHotSpotCount = 0; + this.blockerCount = 0; + this.criticalCount = 0; + this.majorCount = 0; + this.minorCount = 0; + this.infoCount = 0; + profileLanguages.clear(); ignoreRules.clear(); ignoreIssueCount = 0; filters.clear(); + ruleKeys.clear(); } public int getUpdatedFilesIssueCount() { @@ -292,4 +344,41 @@ public Set getFilters() { public static ProblemCacheService getInstance(@NotNull Project project) { return ServiceManager.getService(project, ProblemCacheService.class); } + + public int getBlockerCount() { + return blockerCount; + } + + public int getCriticalCount() { + return criticalCount; + } + + public int getMajorCount() { + return majorCount; + } + + public int getMinorCount() { + return minorCount; + } + + public int getInfoCount() { + return infoCount; + } + + public int severityTotalCount() { + return blockerCount + criticalCount + majorCount + minorCount + infoCount; + } + + public Set getRuleKeys() { + return ruleKeys; + } + + public ConcurrentMap> getFilteredIssues() { + return isFilter() ? filteredIssues : issues; + } + + private boolean isFilter() { + return !filters.isEmpty() || !ruleKeys.isEmpty(); + } + } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 471791f..b3a7402 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -15,6 +15,12 @@ 0.2.3 +
    +
  • Feat Issue severity filter(From ForeveroLo).
  • +
  • Feat Issue ruleKey search.
  • +
  • Fix duplication filter.
  • +

0.2.2

  • Fix report display error, error occurs when git changelist file is renamed or deleted.
  • diff --git a/src/main/resources/i18n/Messages.properties b/src/main/resources/i18n/Messages.properties index 837c653..b443fa9 100644 --- a/src/main/resources/i18n/Messages.properties +++ b/src/main/resources/i18n/Messages.properties @@ -92,4 +92,10 @@ com.yujunyang.intellij.plugin.sonar.task.testConnection.title=测试连接到Son com.yujunyang.intellij.plugin.sonar.task.testConnection.text=正在连接到服务器 {0} com.yujunyang.intellij.plugin.sonar.task.analysis.title=对项目[{0}]执行Sonar代码检查 com.yujunyang.intellij.plugin.sonar.settings.uiLanguages.label=语言: -com.yujunyang.intellij.plugin.sonar.settings.uiLanguages.switchSuccess=切换语言成功,重启后生效 \ No newline at end of file +com.yujunyang.intellij.plugin.sonar.settings.uiLanguages.switchSuccess=切换语言成功,重启后生效 +com.yujunyang.intellij.plugin.sonar.toolWindow.report.displayControl.severityTitle=严重程度 +com.yujunyang.intellij.plugin.sonar.severity.blocker=阻断 +com.yujunyang.intellij.plugin.sonar.severity.critical=严重 +com.yujunyang.intellij.plugin.sonar.severity.major=主要 +com.yujunyang.intellij.plugin.sonar.severity.minor=次要 +com.yujunyang.intellij.plugin.sonar.severity.info=提示 \ No newline at end of file diff --git a/src/main/resources/i18n/Messages_en.properties b/src/main/resources/i18n/Messages_en.properties index 85ce841..82c95fb 100644 --- a/src/main/resources/i18n/Messages_en.properties +++ b/src/main/resources/i18n/Messages_en.properties @@ -92,4 +92,10 @@ com.yujunyang.intellij.plugin.sonar.task.testConnection.title=Test connection to com.yujunyang.intellij.plugin.sonar.task.testConnection.text=Connecting to server {0} com.yujunyang.intellij.plugin.sonar.task.analysis.title=Running Sonar analysis for project [{0}] com.yujunyang.intellij.plugin.sonar.settings.uiLanguages.label=Language: -com.yujunyang.intellij.plugin.sonar.settings.uiLanguages.switchSuccess=Switch language success,restart to get effect \ No newline at end of file +com.yujunyang.intellij.plugin.sonar.settings.uiLanguages.switchSuccess=Switch language success,restart to get effect +com.yujunyang.intellij.plugin.sonar.toolWindow.report.displayControl.severityTitle=Severity +com.yujunyang.intellij.plugin.sonar.severity.blocker=Blocker +com.yujunyang.intellij.plugin.sonar.severity.critical=Critical +com.yujunyang.intellij.plugin.sonar.severity.major=Major +com.yujunyang.intellij.plugin.sonar.severity.minor=Minor +com.yujunyang.intellij.plugin.sonar.severity.info=Info \ No newline at end of file