11package io .snyk .eclipse .plugin .views .snyktoolview ;
22
3+ import java .nio .file .Path ;
34import java .nio .file .Paths ;
5+ import java .util .Map ;
6+ import java .util .Set ;
47import java .util .concurrent .CompletableFuture ;
5-
8+ import java .util .concurrent .ExecutionException ;
9+ import java .util .concurrent .TimeUnit ;
10+ import java .util .concurrent .TimeoutException ;
11+
12+ import org .eclipse .core .resources .IProject ;
13+ import org .eclipse .core .runtime .IProgressMonitor ;
14+ import org .eclipse .core .runtime .IStatus ;
15+ import org .eclipse .core .runtime .Status ;
16+ import org .eclipse .core .runtime .jobs .Job ;
17+ import org .eclipse .jface .action .Action ;
618import org .eclipse .jface .action .IMenuManager ;
719import org .eclipse .jface .action .MenuManager ;
820import org .eclipse .jface .viewers .ISelectionChangedListener ;
1123import org .eclipse .jface .viewers .TreeNode ;
1224import org .eclipse .jface .viewers .TreeViewer ;
1325import org .eclipse .lsp4e .LSPEclipseUtils ;
26+ import org .eclipse .lsp4j .MessageParams ;
27+ import org .eclipse .lsp4j .MessageType ;
1428import org .eclipse .swt .SWT ;
1529import org .eclipse .swt .browser .Browser ;
1630import org .eclipse .swt .custom .SashForm ;
1731import org .eclipse .swt .layout .FillLayout ;
1832import org .eclipse .swt .layout .GridData ;
1933import org .eclipse .swt .layout .GridLayout ;
2034import org .eclipse .swt .widgets .Composite ;
35+ import org .eclipse .swt .widgets .Control ;
2136import org .eclipse .swt .widgets .Display ;
2237import org .eclipse .swt .widgets .Menu ;
2338import org .eclipse .swt .widgets .Tree ;
2641import org .eclipse .ui .menus .CommandContributionItemParameter ;
2742import org .eclipse .ui .part .ViewPart ;
2843
44+ import io .snyk .eclipse .plugin .domain .ProductConstants ;
2945import io .snyk .eclipse .plugin .properties .preferences .FolderConfigs ;
3046import io .snyk .eclipse .plugin .properties .preferences .Preferences ;
3147import io .snyk .eclipse .plugin .utils .ResourceUtils ;
48+ import io .snyk .eclipse .plugin .utils .SnykLogger ;
3249import io .snyk .eclipse .plugin .views .snyktoolview .providers .TreeContentProvider ;
3350import io .snyk .eclipse .plugin .views .snyktoolview .providers .TreeLabelProvider ;
51+ import io .snyk .languageserver .CommandHandler ;
3452import io .snyk .languageserver .protocolextension .SnykExtendedLanguageClient ;
53+ import io .snyk .languageserver .protocolextension .messageObjects .scanResults .Issue ;
3554
3655/**
3756 * TODO This view will replace the old SnykView. Move the snyktoolview classes
@@ -49,6 +68,7 @@ public class SnykToolView extends ViewPart implements ISnykToolView {
4968 private Browser browser ;
5069 private BrowserHandler browserHandler ;
5170 private FolderConfigs folderConfigs = FolderConfigs .getInstance ();
71+ private TreeNode selectedNode ;
5272
5373 @ Override
5474 public void createPartControl (Composite parent ) {
@@ -71,7 +91,7 @@ public void createPartControl(Composite parent) {
7191 treeViewer .setInput (new RootNode ());
7292 treeViewer .expandAll ();
7393
74- registerTreeContextMeny ( parent );
94+ registerTreeContextMenu ( treeViewer . getControl () );
7595
7696 // Create Browser
7797 // SWT.EDGE will be ignored if OS not windows and will be set to SWT.NONE.
@@ -83,29 +103,29 @@ public void createPartControl(Composite parent) {
83103
84104 // Add selection listener to the tree
85105 treeViewer .addSelectionChangedListener (new ISelectionChangedListener () {
106+
86107 @ SuppressWarnings ("restriction" )
87108 @ Override
88109 public void selectionChanged (SelectionChangedEvent event ) {
89110 Display .getDefault ().asyncExec (() -> {
90111 IStructuredSelection selection = (IStructuredSelection ) event .getSelection ();
91112 if (selection .isEmpty ())
92113 return ;
93- TreeNode node = (TreeNode ) selection .getFirstElement ();
94- browserHandler .updateBrowserContent (node );
95- if (node instanceof IssueTreeNode ) {
96- IssueTreeNode issueTreeNode = (IssueTreeNode ) node ;
114+ selectedNode = (TreeNode ) selection .getFirstElement ();
115+ browserHandler .updateBrowserContent (selectedNode );
116+ if (selectedNode instanceof IssueTreeNode ) {
117+ IssueTreeNode issueTreeNode = (IssueTreeNode ) selectedNode ;
97118 FileTreeNode fileNode = (FileTreeNode ) issueTreeNode .getParent ();
98119 LSPEclipseUtils .open (fileNode .getPath ().toUri ().toASCIIString (),
99120 issueTreeNode .getIssue ().getLSP4JRange ());
100121 }
101122 boolean deltaEnabled = Preferences .isDeltaEnabled ();
102- if (node instanceof ContentRootNode && deltaEnabled ) {
103- ContentRootNode contentNode = (ContentRootNode ) node ;
123+ if (selectedNode instanceof ContentRootNode && deltaEnabled ) {
124+ ContentRootNode contentNode = (ContentRootNode ) selectedNode ;
104125 String [] localBranches = folderConfigs .getLocalBranches (contentNode .getPath ())
105126 .toArray (new String [0 ]);
106127
107- new BaseBranchDialog ().open (Display .getDefault (), contentNode .getPath (),
108- localBranches );
128+ new BaseBranchDialog ().open (Display .getDefault (), contentNode .getPath (), localBranches );
109129 }
110130 });
111131 }
@@ -115,11 +135,97 @@ public void selectionChanged(SelectionChangedEvent event) {
115135 this .enableDelta ();
116136 }
117137
118- private void registerTreeContextMeny ( Composite parent ) {
138+ private void registerTreeContextMenu ( Control control ) {
119139 MenuManager menuMgr = new MenuManager ("treemenu" );
120- Menu menu = menuMgr .createContextMenu (parent );
140+ Menu menu = menuMgr .createContextMenu (control );
121141 getSite ().registerContextMenu (menuMgr , null );
122- parent .setMenu (menu );
142+ control .setMenu (menu );
143+
144+ Action ignoreAction = getIgnoreAction ();
145+ Action monitorAction = getMonitorAction ();
146+
147+ menuMgr .add (ignoreAction );
148+ menuMgr .add (monitorAction );
149+ }
150+
151+ private Action getIgnoreAction () {
152+ return new Action ("Ignore issue in .snyk" ) {
153+ @ Override
154+ public void run () {
155+ CompletableFuture .runAsync (() -> {
156+ IssueTreeNode itn = (IssueTreeNode ) selectedNode ;
157+ Issue issue = itn .getIssue ();
158+ new Job ("Ignoring issue " + issue .getDisplayTitle ()) {
159+
160+ @ Override
161+ protected IStatus run (IProgressMonitor monitor ) {
162+ try {
163+ var result = CommandHandler .getInstance ().ignoreIssue (issue ).get (10 , TimeUnit .SECONDS );
164+ outputCommandResult (result );
165+ itn .setText ("[ IGNORED ] " + itn .getText ());
166+ Display .getDefault ().asyncExec (() -> {
167+ treeViewer .refresh (itn , true );
168+ });
169+ } catch (InterruptedException e ) {
170+ Thread .currentThread ().interrupt ();
171+ SnykLogger .logError (e );
172+ return Status .CANCEL_STATUS ;
173+ } catch (ExecutionException | TimeoutException e ) {
174+ SnykLogger .logError (e );
175+ return Status .CANCEL_STATUS ;
176+ }
177+ return Status .OK_STATUS ;
178+ }
179+ }.schedule ();
180+ });
181+ }
182+
183+ public boolean isEnabled () {
184+ return selectedNode instanceof IssueTreeNode && CommandHandler .getInstance ().canBeIgnored (getProduct ());
185+ }
186+
187+ protected String getProduct () {
188+ var pn = (ProductTreeNode ) selectedNode .getParent ().getParent ();
189+ String product = pn .getProduct ();
190+ return product ;
191+ }
192+ };
193+ }
194+
195+ private Action getMonitorAction () {
196+ return new Action ("Monitor project" ) {
197+ @ Override
198+ public void run () {
199+ CompletableFuture .runAsync (() -> {
200+ IssueTreeNode itn = (IssueTreeNode ) selectedNode ;
201+ Issue issue = itn .getIssue ();
202+ IProject project = ResourceUtils .getProjectByPath (Paths .get (issue .filePath ()));
203+ new Job ("Monitoring project " + project .getName ()) {
204+
205+ @ Override
206+ protected IStatus run (IProgressMonitor monitor ) {
207+ try {
208+ Path workingDir = ResourceUtils .getFullPath (project );
209+ var result = CommandHandler .getInstance ().monitorProject (workingDir ).get ();
210+ outputCommandResult (result );
211+ } catch (InterruptedException e ) {
212+ Thread .currentThread ().interrupt ();
213+ SnykLogger .logError (e );
214+ return Status .CANCEL_STATUS ;
215+ } catch (ExecutionException e ) {
216+ SnykLogger .logError (e );
217+ return Status .CANCEL_STATUS ;
218+ }
219+ return Status .OK_STATUS ;
220+ }
221+ }.schedule ();
222+ });
223+ }
224+
225+ public boolean isEnabled () {
226+ return true ;
227+ }
228+ };
123229 }
124230
125231 @ Override
@@ -318,4 +424,20 @@ private void addCommandIfNotPresent(IMenuManager menu, String commandId) {
318424 }
319425 }
320426
427+ @ SuppressWarnings ("restriction" )
428+ protected void outputCommandResult (Object result ) {
429+ if (result != null && result instanceof Map ) {
430+ @ SuppressWarnings ("unchecked" )
431+ Map <String , Object > resultMap = (Map <String , Object >) result ;
432+ String stdOut = resultMap .get ("stdOut" ).toString ();
433+ boolean exitCode = (Double ) resultMap .get ("exitCode" ) == 0 ;
434+ if (exitCode ) {
435+ MessageParams messageParams = new MessageParams (MessageType .Info , stdOut );
436+ SnykExtendedLanguageClient .getInstance ().showMessage (messageParams );
437+ } else {
438+ SnykLogger .logError (new RuntimeException (stdOut ));
439+ }
440+ }
441+ }
442+
321443}
0 commit comments