Skip to content

Commit cda022e

Browse files
authored
Merge pull request #226 from snyk/feat/IDE-715_filter-tree
Feat/ide 715 filter tree
2 parents cefc646 + a46c536 commit cda022e

27 files changed

Lines changed: 652 additions & 173 deletions

plugin/plugin.xml

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,15 @@
141141
name="Ignored Issues">
142142
</command>
143143
<command
144-
defaultHandler="io.snyk.eclipse.plugin.views.snyktoolview.handlers.snykFilterFixableIssuesHandler"
144+
defaultHandler="io.snyk.eclipse.plugin.views.snyktoolview.handlers.FilterFixableIssuesHandler"
145145
id="io.snyk.eclipse.plugin.commands.snykFilterFixableIssues"
146146
name="AI Fixable">
147147
</command>
148+
<command
149+
defaultHandler="io.snyk.eclipse.plugin.views.snyktoolview.handlers.FilterOssFixableIssuesHandler"
150+
id="io.snyk.eclipse.plugin.commands.snykFilterOssFixableIssues"
151+
name="Fixable">
152+
</command>
148153
<command
149154
defaultHandler="io.snyk.eclipse.plugin.views.snyktoolview.handlers.EnableAllAiFixHandler"
150155
id="io.snyk.eclipse.plugin.snykShowAllSeverities"
@@ -354,19 +359,19 @@
354359
style="push"
355360
tooltip="Show Only Net New Issues">
356361
</command>
357-
<separator
358-
name="io.snyk.eclipse.plugin.separator.allIssues"
359-
visible="true">
360-
</separator>
361-
<command
362-
commandId="io.snyk.eclipse.plugin.command.snykShowAllIssuesStatus"
363-
icon="icons/enabled.png"
364-
style="push"
365-
tooltip="Show all issues">
366-
</command>
367362
</menu>
368363
<menu
369-
id="io.snyk.eclipse.plugin.views.snyktoolview.filtersMenu"
364+
id="io.snyk.eclipse.plugin.views.snyktoolview.filtersAiFixMenu"
365+
label="Open Source Fixability">
366+
<command
367+
commandId="io.snyk.eclipse.plugin.commands.snykFilterOssFixableIssues"
368+
icon="icons/enabled.png"
369+
style="push"
370+
tooltip="Show only issues with Open Source Upgrade suggestions">
371+
</command>
372+
</menu>
373+
<menu
374+
id="io.snyk.eclipse.plugin.views.snyktoolview.filtersOssMenu"
370375
label="Code AI Fixability">
371376
<command
372377
commandId="io.snyk.eclipse.plugin.commands.snykFilterFixableIssues"

plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/Preferences.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
5454
public static final String FILTER_IGNORES_SHOW_OPEN_ISSUES = "FILTER_IGNORES_OPEN_ISSUES";
5555
public static final String FILTER_IGNORES_SHOW_IGNORED_ISSUES = "FILTER_IGNORES_IGNORED_ISSUES";
5656
public static final String FILTER_FIXABLE_ISSUES = "FILTER_FIXABLE_ISSUES";
57+
public static final String FILTER_OSS_FIXABLE_ISSUES = "FILTER_OSS_FIXABLE_ISSUES";
5758

5859
// Feature flags
5960
public static final String IS_GLOBAL_IGNORES_FEATURE_ENABLED = "IS_GLOBAL_IGNORES_FEATURE_ENABLED";
@@ -68,6 +69,7 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
6869
public static final String DEFAULT_ENDPOINT = "https://api.snyk.io";
6970
public static final String DEVICE_ID = "deviceId";
7071
public static final String RELEASE_CHANNEL = "releaseChannel";
72+
7173

7274
private final PreferenceStore store;
7375

@@ -97,9 +99,6 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
9799
if (getPref(FILTER_LOW) == null) {
98100
store(FILTER_LOW, "false");
99101
}
100-
if (getPref(FILTER_CRITICAL) == null) {
101-
store(FILTER_CRITICAL, "false");
102-
}
103102
if (getPref(FILTER_DELTA_NEW_ISSUES) == null) {
104103
store(FILTER_DELTA_NEW_ISSUES, "false");
105104
}
@@ -112,7 +111,10 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
112111
if (getPref(FILTER_FIXABLE_ISSUES) == null) {
113112
store(FILTER_FIXABLE_ISSUES, "false");
114113
}
115-
114+
if (getPref(FILTER_OSS_FIXABLE_ISSUES) == null) {
115+
store(FILTER_OSS_FIXABLE_ISSUES, "false");
116+
}
117+
116118
if (getPref(SEND_ERROR_REPORTS) == null) {
117119
store(SEND_ERROR_REPORTS, "true");
118120
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package io.snyk.eclipse.plugin.views.snyktoolview;
2+
3+
import java.util.function.Predicate;
4+
5+
import org.eclipse.jface.viewers.TreeViewer;
6+
7+
import io.snyk.eclipse.plugin.SnykStartup;
8+
import io.snyk.eclipse.plugin.properties.preferences.Preferences;
9+
import io.snyk.eclipse.plugin.views.snyktoolview.filters.FixableFilter;
10+
import io.snyk.eclipse.plugin.views.snyktoolview.filters.IgnoresFilter;
11+
import io.snyk.eclipse.plugin.views.snyktoolview.filters.IgnoresOpenIssuesFilter;
12+
import io.snyk.eclipse.plugin.views.snyktoolview.filters.OssFixableFilter;
13+
import io.snyk.eclipse.plugin.views.snyktoolview.filters.SeverityCriticalFilter;
14+
import io.snyk.eclipse.plugin.views.snyktoolview.filters.SeverityHighFilter;
15+
import io.snyk.eclipse.plugin.views.snyktoolview.filters.SeverityLowFilter;
16+
import io.snyk.eclipse.plugin.views.snyktoolview.filters.SeverityMediumFilter;
17+
import io.snyk.languageserver.protocolextension.messageObjects.scanResults.Issue;
18+
19+
public class TreeFilterManager {
20+
21+
private TreeViewer treeView;
22+
private TreeViewerFilter filter;
23+
private static TreeFilterManager filterManager;
24+
25+
public synchronized static TreeFilterManager getInstance() {
26+
if (filterManager != null) {
27+
return filterManager;
28+
}
29+
filterManager = new TreeFilterManager();
30+
31+
setupFilters();
32+
return filterManager;
33+
}
34+
35+
private static void setupFilters() {
36+
// Severity filters
37+
new SeverityCriticalFilter(TreeFilterManager.getInstance(), Preferences.getInstance(),
38+
Preferences.FILTER_CRITICAL).applyFilter();
39+
new SeverityHighFilter(TreeFilterManager.getInstance(), Preferences.getInstance(), Preferences.FILTER_HIGH)
40+
.applyFilter();
41+
new SeverityMediumFilter(TreeFilterManager.getInstance(), Preferences.getInstance(), Preferences.FILTER_MEDIUM)
42+
.applyFilter();
43+
new SeverityLowFilter(TreeFilterManager.getInstance(), Preferences.getInstance(), Preferences.FILTER_LOW)
44+
.applyFilter();
45+
46+
// Ignores filters
47+
new IgnoresFilter(TreeFilterManager.getInstance(), Preferences.getInstance(),
48+
Preferences.FILTER_IGNORES_SHOW_IGNORED_ISSUES).applyFilter();
49+
new IgnoresOpenIssuesFilter(TreeFilterManager.getInstance(), Preferences.getInstance(),
50+
Preferences.FILTER_IGNORES_SHOW_OPEN_ISSUES).applyFilter();
51+
52+
// Fix
53+
new FixableFilter(TreeFilterManager.getInstance(), Preferences.getInstance(), Preferences.FILTER_FIXABLE_ISSUES)
54+
.applyFilter();
55+
new OssFixableFilter(TreeFilterManager.getInstance(), Preferences.getInstance(),
56+
Preferences.FILTER_OSS_FIXABLE_ISSUES).applyFilter();
57+
58+
}
59+
60+
private TreeFilterManager() {
61+
treeView = SnykStartup.getView().getTreeViewer();
62+
filter = new TreeViewerFilter();
63+
}
64+
65+
public void addTreeFilter(String filterName, Predicate<? super Issue> filterPredicate) {
66+
filter.setFilterPredicate(filterName, filterPredicate);
67+
treeView.addFilter(filter);
68+
updateTree(treeView);
69+
}
70+
71+
public void removeTreeFilter(String filterName) {
72+
filter.removeFilterPredicate(filterName);
73+
treeView.addFilter(filter);
74+
updateTree(treeView);
75+
}
76+
77+
public void removeTreeFilters() {
78+
treeView.resetFilters();
79+
updateTree(treeView);
80+
}
81+
82+
private void updateTree(TreeViewer treeView) {
83+
treeView.getControl().setRedraw(false);
84+
treeView.refresh();
85+
treeView.getControl().setRedraw(true);
86+
treeView.expandAll();
87+
}
88+
89+
}
Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,66 @@
11
package io.snyk.eclipse.plugin.views.snyktoolview;
22

3-
import java.util.ArrayList;
4-
import java.util.List;
3+
import java.util.Map;
4+
import java.util.concurrent.ConcurrentHashMap;
5+
import java.util.function.Predicate;
56

6-
import org.eclipse.jface.viewers.ILabelProvider;
7+
import org.eclipse.jface.viewers.ITreeContentProvider;
78
import org.eclipse.jface.viewers.TreeViewer;
89
import org.eclipse.jface.viewers.Viewer;
910
import org.eclipse.jface.viewers.ViewerFilter;
1011

12+
import io.snyk.languageserver.protocolextension.messageObjects.scanResults.Issue;
13+
1114
public class TreeViewerFilter extends ViewerFilter {
12-
private List<String> searchStrings;
13-
private boolean matchAll; // If true, all filters must match; if false, any filter can match
15+
private Map<String, Predicate<? super Issue>> filters;
1416

1517
public TreeViewerFilter() {
16-
this.searchStrings = new ArrayList<>();
17-
this.matchAll = true; // Default to matching all filters
18+
filters = new ConcurrentHashMap<>();
1819
}
1920

20-
public void addSearchText(String s) {
21-
if (s != null && !s.isEmpty()) {
22-
this.searchStrings.add(".*" + s.toLowerCase() + ".*");
23-
}
24-
}
21+
@Override
22+
public boolean select(Viewer viewer, Object parentElement, Object element) {
23+
if (element instanceof FileTreeNode) {
24+
return hasVisibleChildren((FileTreeNode) element, viewer);
25+
}
26+
27+
if (!(element instanceof IssueTreeNode) || !(viewer instanceof TreeViewer)) {
28+
return true;
29+
}
2530

26-
public void clearSearchText() {
27-
this.searchStrings.clear();
31+
return isIssueVisible((IssueTreeNode) element);
2832
}
2933

30-
public void setMatchAll(boolean matchAll) {
31-
this.matchAll = matchAll;
34+
private boolean hasVisibleChildren(FileTreeNode fileNode, Viewer viewer) {
35+
Object[] children = ((ITreeContentProvider) ((TreeViewer) viewer).getContentProvider()).getChildren(fileNode);
36+
for (Object child : children) {
37+
if (child instanceof IssueTreeNode && isIssueVisible((IssueTreeNode) child)) {
38+
return true;
39+
}
40+
}
41+
return false;
3242
}
3343

34-
@Override
35-
public boolean select(Viewer viewer, Object parentElement, Object element) {
36-
if (searchStrings.isEmpty()) {
37-
return true;
38-
}
39-
40-
TreeViewer treeViewer = (TreeViewer) viewer;
41-
String label = ((ILabelProvider) treeViewer.getLabelProvider()).getText(element);
44+
private boolean isIssueVisible(IssueTreeNode issueNode) {
45+
Issue issue = issueNode.getIssue();
46+
if (issue == null) {
47+
return true;
48+
}
4249

43-
if (label == null) {
44-
return false;
45-
}
50+
for (var filter : this.filters.values()) {
51+
if (!filter.test(issue)) {
52+
return false;
53+
}
54+
}
55+
return true;
56+
}
4657

47-
String labelLower = label.toLowerCase();
58+
public void setFilterPredicate(String filterName, Predicate<? super Issue> predicate) {
59+
this.filters.put(filterName, predicate);
60+
}
4861

49-
if (matchAll) {
50-
return searchStrings.stream().allMatch(s -> labelLower.matches(s));
51-
} else {
52-
return searchStrings.stream().anyMatch(s -> labelLower.matches(s));
53-
}
62+
public void removeFilterPredicate(String filterName) {
63+
this.filters.remove(filterName);
5464
}
65+
5566
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.snyk.eclipse.plugin.views.snyktoolview.filters;
2+
3+
public interface BaseFilter {
4+
public void applyFilter();
5+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.snyk.eclipse.plugin.views.snyktoolview.filters;
2+
3+
import io.snyk.eclipse.plugin.properties.preferences.Preferences;
4+
import io.snyk.eclipse.plugin.views.snyktoolview.TreeFilterManager;
5+
6+
public class FixableFilter implements BaseFilter {
7+
private TreeFilterManager filterManager;
8+
private Preferences preferences;
9+
private String preferenceKey;
10+
11+
public FixableFilter(TreeFilterManager filterManager, Preferences preferences, String preferenceKey) {
12+
this.filterManager = filterManager;
13+
this.preferences = preferences;
14+
this.preferenceKey = preferenceKey;
15+
16+
}
17+
18+
@Override
19+
public void applyFilter() {
20+
boolean booleanPref = this.preferences.getBooleanPref(this.preferenceKey);
21+
22+
if (booleanPref) {
23+
this.filterManager.addTreeFilter(this.preferenceKey, issue -> issue.hasFix());
24+
} else {
25+
this.filterManager.removeTreeFilter(this.preferenceKey);
26+
}
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.snyk.eclipse.plugin.views.snyktoolview.filters;
2+
3+
import io.snyk.eclipse.plugin.properties.preferences.Preferences;
4+
import io.snyk.eclipse.plugin.views.snyktoolview.TreeFilterManager;
5+
6+
public class IgnoresFilter implements BaseFilter {
7+
private TreeFilterManager filterManager;
8+
private Preferences preferences;
9+
private String preferenceKey;
10+
11+
public IgnoresFilter(TreeFilterManager filterManager, Preferences preferences, String preferenceKey) {
12+
this.filterManager = filterManager;
13+
this.preferences = preferences;
14+
this.preferenceKey = preferenceKey;
15+
}
16+
17+
@Override
18+
public void applyFilter() {
19+
boolean booleanPref = this.preferences.getBooleanPref(this.preferenceKey);
20+
21+
if (booleanPref) {
22+
filterManager.removeTreeFilter(preferenceKey);
23+
} else {
24+
filterManager.addTreeFilter(preferenceKey, issue -> !issue.isIgnored());
25+
}
26+
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.snyk.eclipse.plugin.views.snyktoolview.filters;
2+
3+
import io.snyk.eclipse.plugin.properties.preferences.Preferences;
4+
import io.snyk.eclipse.plugin.views.snyktoolview.TreeFilterManager;
5+
6+
public class IgnoresOpenIssuesFilter implements BaseFilter {
7+
private TreeFilterManager filterManager;
8+
private Preferences preferences;
9+
private String preferenceKey;
10+
11+
public IgnoresOpenIssuesFilter(TreeFilterManager filterManager, Preferences preferences, String preferenceKey) {
12+
this.filterManager = filterManager;
13+
this.preferences = preferences;
14+
this.preferenceKey = preferenceKey;
15+
}
16+
17+
@Override
18+
public void applyFilter() {
19+
boolean booleanPref = this.preferences.getBooleanPref(Preferences.FILTER_IGNORES_SHOW_OPEN_ISSUES);
20+
21+
if (booleanPref) {
22+
filterManager.removeTreeFilter(preferenceKey);
23+
} else {
24+
filterManager.addTreeFilter(preferenceKey, issue -> issue.isIgnored());
25+
}
26+
27+
}
28+
}

0 commit comments

Comments
 (0)