diff --git a/README.adoc b/README.adoc
index bd08256..4fd0a2a 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,28 +1,38 @@
-= sonarlint4netbeans
-
-== SonarLint integration for Apache Netbeans
-
-Features:
-
-- Support Java and Javascript
-- Annotation in editor
-- Type SonarLint in Action Items
-- Enable/Disable Rules in Tools/Options/Miscellaneous/SonarLint
-- Severity icons
-
-== Screenshot
-
-.SonarLint in Java editor and show action items for selected project
-image::docs/JavaEditorAnnotationAndActionItems.jpg[]
-
-.Show Action Items fo currently edited file only
-image::docs/JavascriptActionItems.jpg[]
-
-.SonarLint analyzer name and version
-image::docs/OptionsSonarLintAnalyzers.jpg[]
-
-.SonarLint rules enabled or disabled
-image::docs/OptionsSonarLintRules.jpg[]
-
-.Sonar rule details window
-image::docs/SonarRuleDetailsWindow.jpg[]
\ No newline at end of file
+= sonarlint4netbeans
+
+== SonarLint integration for Apache Netbeans
+
+Features:
+
+- Support Java and Javascript
+- Annotation in editor
+- Type SonarLint in Action Items
+- Enable/Disable Rules in Tools/Options/Miscellaneous/SonarLint
+- Filter Rules in Tools/Options/Miscellaneous/SonarLint option panel and "Sonar Rule Details" window
+- Severity icons
+
+== Screenshot
+
+.SonarLint in Java editor and show action items for selected project
+image::docs/JavaEditorAnnotationAndActionItems.jpg[]
+
+.Show Action Items fo currently edited file only
+image::docs/JavascriptActionItems.jpg[]
+
+.SonarLint analyzer name and version
+image::docs/OptionsSonarLintAnalyzers.jpg[]
+
+.SonarLint rules enabled or disabled
+image::docs/OptionsSonarLintRules.jpg[]
+
+.SonarLint rules enabled or disabled with key filter
+image::docs/OptionsSonarLintRulesWithKeyFilter.jpg[]
+
+.SonarLint rules enabled or disabled with name filter
+image::docs/OptionsSonarLintRulesWithNameFilter.jpg[]
+
+.Sonar rule details window with key filter
+image::docs/SonarRuleDetailsWindowWithKeyFilter.jpg[]
+
+.Sonar rule details window with name filter
+image::docs/SonarRuleDetailsWindowWithNameFilter.jpg[]
\ No newline at end of file
diff --git a/docs/OptionsSonarLintRules.jpg b/docs/OptionsSonarLintRules.jpg
index 2c061cf..c433963 100644
Binary files a/docs/OptionsSonarLintRules.jpg and b/docs/OptionsSonarLintRules.jpg differ
diff --git a/docs/OptionsSonarLintRulesWithKeyFilter.jpg b/docs/OptionsSonarLintRulesWithKeyFilter.jpg
new file mode 100644
index 0000000..b7b0d71
Binary files /dev/null and b/docs/OptionsSonarLintRulesWithKeyFilter.jpg differ
diff --git a/docs/OptionsSonarLintRulesWithNameFilter.jpg b/docs/OptionsSonarLintRulesWithNameFilter.jpg
new file mode 100644
index 0000000..4d27e12
Binary files /dev/null and b/docs/OptionsSonarLintRulesWithNameFilter.jpg differ
diff --git a/docs/SonarRuleDetailsWindow.jpg b/docs/SonarRuleDetailsWindowWithKeyFilter.jpg
similarity index 100%
rename from docs/SonarRuleDetailsWindow.jpg
rename to docs/SonarRuleDetailsWindowWithKeyFilter.jpg
diff --git a/docs/SonarRuleDetailsWindowWithNameFilter.jpg b/docs/SonarRuleDetailsWindowWithNameFilter.jpg
new file mode 100644
index 0000000..dc7cb99
Binary files /dev/null and b/docs/SonarRuleDetailsWindowWithNameFilter.jpg differ
diff --git a/pom.xml b/pom.xml
index 786269a..5612387 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
fr.philippefichet.sonarlint
sonarlint4netbeans
- 1.3.0
+ 1.4.0
nbm
SonarLint for Netbeans
diff --git a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintPanel.form b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintPanel.form
index 452849f..be494fc 100644
--- a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintPanel.form
+++ b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintPanel.form
@@ -22,6 +22,11 @@
-->
diff --git a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintPanel.java b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintPanel.java
index c2123fb..b49d0aa 100644
--- a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintPanel.java
+++ b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintPanel.java
@@ -21,24 +21,28 @@
import java.awt.BorderLayout;
import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.stream.Collectors;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
+import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
+import javax.swing.JSeparator;
import javax.swing.JTable;
+import javax.swing.JTextField;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import org.openide.util.Lookup;
-import org.sonarsource.sonarlint.core.client.api.common.RuleDetails;
import org.sonarsource.sonarlint.core.client.api.common.RuleKey;
import org.sonarsource.sonarlint.core.client.api.connected.LoadedAnalyzer;
@@ -49,17 +53,7 @@ public final class SonarLintPanel extends javax.swing.JPanel {
private final Map ruleKeyChanged = new HashMap<>();
private DefaultTableModel analyzerDefaultTableModel = new DefaultTableModel();
- private DefaultTableModel rulesDefaultTableModel = new DefaultTableModel() {
- @Override
- public boolean isCellEditable(int row, int column) {
- return column < 1;
- }
-
- @Override
- public Class> getColumnClass(int columnIndex) {
- return columnIndex == 0 ? Boolean.class : String.class;
- }
- };
+ private SonarLintRuleTableModel rulesDefaultTableModel = new SonarLintRuleTableModel();
public SonarLintPanel(SonarLintOptionsPanelController controller) {
this.controller = controller;
@@ -88,23 +82,7 @@ public SonarLintPanel(SonarLintOptionsPanelController controller) {
});
}
- rulesDefaultTableModel.addColumn("");
- rulesDefaultTableModel.addColumn("Language");
- rulesDefaultTableModel.addColumn("Severity");
- rulesDefaultTableModel.addColumn("Key");
- rulesDefaultTableModel.addColumn("Details");
- Collection allRuleDetails = engine.getAllRuleDetails();
- allRuleDetails.stream().sorted((r1, r2) -> {
- return r1.getKey().compareTo(r2.getKey());
- }).map(ruleDetail -> new Object[] {
- !engine.isExcluded(ruleDetail),
- ruleDetail.getLanguageKey(),
- ruleDetail.getSeverity(),
- ruleDetail.getKey(),
- ruleDetail.getName()}
- ).collect(Collectors.toList()).forEach(rulesDefaultTableModel::addRow);
-
- rulesDefaultTableModel.addTableModelListener((e) -> {
+ rulesDefaultTableModel.addTableModelListener(e -> {
controller.changed();
int column = e.getColumn();
@@ -120,7 +98,7 @@ public SonarLintPanel(SonarLintOptionsPanelController controller) {
categoriesList.addListSelectionListener((e) -> {
if ("Rules".equals(categoriesList.getSelectedValue())) {
- initRulesPanel();
+ initRulesPanel(engine);
}
if ("Analyzers".equals(categoriesList.getSelectedValue())) {
initAnalyzersPanel();
@@ -130,7 +108,7 @@ public SonarLintPanel(SonarLintOptionsPanelController controller) {
});
// Rule panel by default
- initRulesPanel();
+ initRulesPanel(engine);
optionPanel.revalidate();
optionPanel.repaint();
});
@@ -144,8 +122,35 @@ private void initAnalyzersPanel() {
optionPanel.add(analyzersTable, BorderLayout.CENTER);
}
- private void initRulesPanel() {
+ private void initRulesPanel(SonarLintEngine engine) {
optionPanel.removeAll();
+
+ JPanel languageKeyContainer = new JPanel(new FlowLayout());
+ JTextField rulesFilter = new JTextField();
+ rulesFilter.setColumns(20);
+ JComboBox comboLanguageKey = new JComboBox<>();
+ engine.getAllRuleDetails().stream()
+ .map(r -> r.getLanguageKey())
+ .distinct()
+ .forEach(comboLanguageKey::addItem);
+ rulesFilter.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyReleased(KeyEvent e) {
+ rulesDefaultTableModel.setRules(engine, (String)comboLanguageKey.getSelectedItem(), rulesFilter.getText());
+ }
+ });
+ comboLanguageKey.addActionListener(
+ e ->
+ rulesDefaultTableModel.setRules(engine, (String)comboLanguageKey.getSelectedItem(), rulesFilter.getText())
+ );
+ languageKeyContainer.add(new JLabel("language key: "));
+ languageKeyContainer.add(comboLanguageKey);
+ languageKeyContainer.add(new JSeparator());
+ languageKeyContainer.add(new JLabel("filter: "));
+ languageKeyContainer.add(rulesFilter);
+
+ JPanel northContainer = new JPanel();
+ northContainer.setLayout(new BoxLayout(northContainer, BoxLayout.Y_AXIS));
JTable rulesTable = new JTable(rulesDefaultTableModel);
rulesTable.getColumnModel().getColumn(0).setMaxWidth(50);
rulesTable.getColumnModel().getColumn(1).setMaxWidth(250);
@@ -162,7 +167,11 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole
return defaultTableCellRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
});
- optionPanel.add(rulesTable.getTableHeader(), BorderLayout.NORTH);
+
+ rulesDefaultTableModel.setRules(engine, (String)comboLanguageKey.getSelectedItem(), rulesFilter.getText());
+ northContainer.add(languageKeyContainer);
+ northContainer.add(rulesTable.getTableHeader());
+ optionPanel.add(northContainer, BorderLayout.NORTH);
optionPanel.add(rulesTable, BorderLayout.CENTER);
}
@@ -178,8 +187,10 @@ private void initComponents() {
categoriesLabel = new javax.swing.JLabel();
categoriesScrollPanel = new javax.swing.JScrollPane();
categoriesList = new javax.swing.JList<>();
+ optionScrollPane = new javax.swing.JScrollPane();
optionPanel = new javax.swing.JPanel();
+ setPreferredSize(getPreferredSize());
setLayout(new java.awt.BorderLayout(10, 0));
categoriesPanel.setLayout(new javax.swing.BoxLayout(categoriesPanel, javax.swing.BoxLayout.PAGE_AXIS));
@@ -192,15 +203,21 @@ private void initComponents() {
public int getSize() { return strings.length; }
public String getElementAt(int i) { return strings[i]; }
});
+ categoriesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ categoriesList.setSelectedIndex(0);
categoriesScrollPanel.setViewportView(categoriesList);
categoriesPanel.add(categoriesScrollPanel);
add(categoriesPanel, java.awt.BorderLayout.WEST);
+ optionScrollPane.setViewportView(null);
+
optionPanel.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
optionPanel.setLayout(new java.awt.BorderLayout());
- add(optionPanel, java.awt.BorderLayout.CENTER);
+ optionScrollPane.setViewportView(optionPanel);
+
+ add(optionScrollPane, java.awt.BorderLayout.CENTER);
}// //GEN-END:initComponents
void load() {
@@ -235,10 +252,11 @@ boolean valid() {
}
// Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JLabel categoriesLabel;
- private javax.swing.JList categoriesList;
- private javax.swing.JPanel categoriesPanel;
- private javax.swing.JScrollPane categoriesScrollPanel;
- private javax.swing.JPanel optionPanel;
+ javax.swing.JLabel categoriesLabel;
+ javax.swing.JList categoriesList;
+ javax.swing.JPanel categoriesPanel;
+ javax.swing.JScrollPane categoriesScrollPanel;
+ javax.swing.JPanel optionPanel;
+ javax.swing.JScrollPane optionScrollPane;
// End of variables declaration//GEN-END:variables
}
diff --git a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintRuleTableModel.java b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintRuleTableModel.java
new file mode 100644
index 0000000..486f73d
--- /dev/null
+++ b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintRuleTableModel.java
@@ -0,0 +1,76 @@
+/*
+ * sonarlint4netbeans: SonarLint integration for Apache Netbeans
+ * Copyright (C) 2020 Philippe FICHET.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package fr.philippefichet.sonarlint.netbeans;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+import javax.swing.table.DefaultTableModel;
+import org.sonarsource.sonarlint.core.client.api.common.RuleDetails;
+
+
+/**
+ *
+ * @author FICHET Philippe
+ */
+public class SonarLintRuleTableModel extends DefaultTableModel {
+
+ public SonarLintRuleTableModel() {
+ init();
+ }
+
+ private void init() {
+ addColumn("");
+ addColumn("Language");
+ addColumn("Severity");
+ addColumn("Key");
+ addColumn("Details");
+ }
+
+ public void setRules(SonarLintEngine engine, String languagekey, String ruleFilter) {
+ while(getRowCount() > 0) {
+ removeRow(0);
+ }
+ Collection allRuleDetails = engine.getAllRuleDetails();
+ allRuleDetails.stream()
+ .filter(
+ SonarLintUtils.FilterBy.languageKey(languagekey)
+ .and(SonarLintUtils.FilterBy.keyAndName(ruleFilter))
+ )
+ .sorted((r1, r2) ->
+ r1.getKey().compareTo(r2.getKey())
+ ).map(ruleDetail -> new Object[] {
+ !engine.isExcluded(ruleDetail),
+ ruleDetail.getLanguageKey(),
+ ruleDetail.getSeverity(),
+ ruleDetail.getKey(),
+ ruleDetail.getName()}
+ ).collect(Collectors.toList()).forEach(this::addRow);
+ }
+
+ @Override
+ public boolean isCellEditable(int row, int column) {
+ return column < 1;
+ }
+
+ @Override
+ public Class> getColumnClass(int columnIndex) {
+ return columnIndex == 0 ? Boolean.class : String.class;
+ }
+}
diff --git a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintUtils.java b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintUtils.java
index 162fa2e..a428c4e 100644
--- a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintUtils.java
+++ b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarLintUtils.java
@@ -29,6 +29,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.function.Predicate;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import org.netbeans.api.project.FileOwnerQuery;
@@ -54,7 +55,34 @@ public final class SonarLintUtils {
private SonarLintUtils() {
}
-
+
+ public static class FilterBy {
+
+ private FilterBy() {
+ }
+
+ /**
+ * Create a predicat to filter rule detail by language key
+ * @param languageKey language key to filter
+ * @return Predicat to filter rule detail by language key
+ */
+ public static Predicate languageKey(String languageKey) {
+ return ruleDetail -> ruleDetail.getLanguageKey().equals(languageKey);
+ }
+
+ /**
+ * Create a predicat to filter rule detail by key or name
+ * @param keyOrName key or name to filter
+ * @return Predicat to filter rule detail by key or name
+ */
+ public static Predicate keyAndName(String keyOrName) {
+ String ruleFilterLowerCase = keyOrName.toLowerCase();
+ return ruleDetail -> keyOrName.isEmpty()
+ || ruleDetail.getKey().toLowerCase().contains(ruleFilterLowerCase)
+ || ruleDetail.getName().toLowerCase().contains(ruleFilterLowerCase);
+ }
+ }
+
public static Optional toImageIcon(String severity)
{
URL resource = SonarLintUtils.class.getClassLoader().getResource("fr/philippefichet/sonarlint/netbeans/resources/sonarlint-" + severity.toLowerCase() + ".png");
@@ -63,7 +91,7 @@ public static Optional toImageIcon(String severity)
}
return Optional.of(new ImageIcon(resource, severity));
}
-
+
public static String toURL(RuleDetails ruleDetails)
{
String[] keySplit = ruleDetails.getKey().split(":");
diff --git a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarRuleDetailsTopComponent.form b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarRuleDetailsTopComponent.form
index 3b9e48c..ee42c10 100644
--- a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarRuleDetailsTopComponent.form
+++ b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarRuleDetailsTopComponent.form
@@ -97,6 +97,7 @@
+
diff --git a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarRuleDetailsTopComponent.java b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarRuleDetailsTopComponent.java
index 87d6116..581ca22 100644
--- a/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarRuleDetailsTopComponent.java
+++ b/src/main/java/fr/philippefichet/sonarlint/netbeans/SonarRuleDetailsTopComponent.java
@@ -138,6 +138,7 @@ public Component getListCellRendererComponent(JList extends String> list, Stri
}
});
initListAllRuleDetails();
+ sonarLintAllRules.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
sonarLintAllRules.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
sonarLintAllRulesValueChanged(evt);
@@ -175,7 +176,7 @@ private void initListAllRuleDetails() {
DefaultListModel model = new DefaultListModel<>();
Collection rules = engine.getAllRuleDetails();
rules.stream().sorted((r1, r2) -> r1.getKey().compareTo(r2.getKey()))
- .filter(rule -> ruleKeyFilter.isEmpty() || rule.getKey().toLowerCase().contains(ruleKeyFilter))
+ .filter(SonarLintUtils.FilterBy.keyAndName(ruleKeyFilter))
.forEach(rule -> model.addElement(rule.getKey()));
sonarLintAllRules.setModel(model);
sonarLintAllRules.updateUI();
diff --git a/src/main/resources/fr/philippefichet/sonarlint/netbeans/Bundle.properties b/src/main/resources/fr/philippefichet/sonarlint/netbeans/Bundle.properties
index 98269f3..7784938 100644
--- a/src/main/resources/fr/philippefichet/sonarlint/netbeans/Bundle.properties
+++ b/src/main/resources/fr/philippefichet/sonarlint/netbeans/Bundle.properties
@@ -7,6 +7,7 @@ Features:\n\
Annotation in editor\
Type SonarLint in Action Items\
Enable/Disable Rules in Tools/Options/Miscellaneous/SonarLint\
+Filter Rules in Tools/Options/Miscellaneous/SonarLint option panel and "Sonar Rule Details" window\
Severity icons\
OpenIDE-Module-Name=sonarlint4netbeans