Skip to content

Commit

Permalink
feat: select treenode on snyk showdocument WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
acke committed Feb 24, 2025
1 parent 25d529a commit 269c2ae
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import org.eclipse.jface.viewers.TreeViewer;

import io.snyk.languageserver.protocolextension.messageObjects.scanResults.Issue;

/**
* This interface captures the externally used methods with the tool window.
* Having it, should allow for easier testing of the business logic apart from
Expand Down Expand Up @@ -125,4 +127,6 @@ static String getPlural(long count) {
* @return
*/
abstract void disableDelta();

abstract void selectTreeNode(Issue issue, String product);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeNode;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.lsp4e.LSPEclipseUtils;
Expand All @@ -42,6 +43,7 @@
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.ViewPart;

import io.snyk.eclipse.plugin.domain.ProductConstants;
import io.snyk.eclipse.plugin.preferences.Preferences;
import io.snyk.eclipse.plugin.properties.FolderConfigs;
import io.snyk.eclipse.plugin.utils.ResourceUtils;
Expand Down Expand Up @@ -477,4 +479,31 @@ protected void outputCommandResult(Object result) {
}
}

@Override
public void selectTreeNode(Issue issue, String product) {
ProductTreeNode productNode = getProductNode(ProductConstants.DISPLAYED_CODE_SECURITY, issue.filePath());
drillDown((TreeNode) productNode, issue);
}

private void drillDown(TreeNode currentParent, Issue issue) {
for (Object child : currentParent.getChildren()) {
TreeNode childNode = (TreeNode) child;

if (childNode instanceof IssueTreeNode && ((IssueTreeNode) childNode).getIssue().id().equals(issue.id())) {
updateSelection((IssueTreeNode) childNode);
return; // Exit the function as we've found a match
}

if (childNode.getChildren() != null && childNode.getChildren().length != 0) {
drillDown(childNode, issue);
}
}
}

private void updateSelection(IssueTreeNode issueTreeNode) {
Display.getDefault().asyncExec(() -> {
IStructuredSelection selection = new StructuredSelection(issueTreeNode);
treeViewer.setSelection(selection, true);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ private LsConstants() {
public static final String SNYK_PUBLISH_DIAGNOSTICS_316 = "$/snyk.publishDiagnostics316";
public static final String SNYK_FOLDER_CONFIG = "$/snyk.folderConfigs";
public static final String SNYK_SCAN_SUMMARY = "$/snyk.scanSummary";
public static final String SNYK_SHOW_DOCUMENT = "$/snyk.showDocument";
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.snyk.languageserver.protocolextension;

import static io.snyk.eclipse.plugin.domain.ProductConstants.DIAGNOSTIC_SOURCE_SNYK_CODE;
import static io.snyk.eclipse.plugin.domain.ProductConstants.DISPLAYED_CODE_QUALITY;
import static io.snyk.eclipse.plugin.domain.ProductConstants.DISPLAYED_CODE_SECURITY;
import static io.snyk.eclipse.plugin.domain.ProductConstants.LSP_SOURCE_TO_SCAN_PARAMS;
Expand All @@ -22,15 +23,20 @@
import static io.snyk.eclipse.plugin.views.snyktoolview.ISnykToolView.getPlural;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
Expand All @@ -47,6 +53,8 @@
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageClientImpl;
import org.eclipse.lsp4j.ProgressParams;
import org.eclipse.lsp4j.ShowDocumentParams;
import org.eclipse.lsp4j.ShowDocumentResult;
import org.eclipse.lsp4j.WorkDoneProgressCreateParams;
import org.eclipse.lsp4j.WorkDoneProgressKind;
import org.eclipse.lsp4j.WorkDoneProgressNotification;
Expand Down Expand Up @@ -116,8 +124,8 @@ public class SnykExtendedLanguageClient extends LanguageClientImpl {

public SnykExtendedLanguageClient() {
super();
//TODO, fix this; Identifies a possible unsafe usage of a static field.
instance = this; //NOPMD
// TODO, fix this; Identifies a possible unsafe usage of a static field.
instance = this; // NOPMD
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
registerPluginInstalledEventTask();
registerRefreshFeatureFlagsTask();
Expand Down Expand Up @@ -384,16 +392,96 @@ public void snykScan(SnykScanParam param) {
this.toolView.refreshBrowser(param.getStatus());
}

@JsonNotification(value = LsConstants.SNYK_FOLDER_CONFIG)
public void folderConfig(FolderConfigsParam folderConfigParam) {
List<FolderConfig> folderConfigs = folderConfigParam != null ? folderConfigParam.getFolderConfigs() : List.of();
CompletableFuture.runAsync(() -> FolderConfigs.getInstance().addAll(folderConfigs));
}

@JsonNotification(value = LsConstants.SNYK_SCAN_SUMMARY)
public void updateSummaryPanel(SummaryPanelParams summary) {
openToolView();
this.toolView.updateSummary(summary.getSummary());
}

@JsonNotification(value = LsConstants.SNYK_FOLDER_CONFIG)
public void folderConfig(FolderConfigsParam folderConfigParam) {
List<FolderConfig> folderConfigs = folderConfigParam != null ? folderConfigParam.getFolderConfigs() : List.of();
CompletableFuture.runAsync(() -> FolderConfigs.getInstance().addAll(folderConfigs));
@Override
public CompletableFuture<ShowDocumentResult> showDocument(ShowDocumentParams params) {
URI uri;
try {
uri = new URI(params.getUri());
} catch (URISyntaxException e) {
SnykLogger.logError(e);
return null;
}

String scheme = uri.getScheme();
String product = getDecodedParam(uri, "product");
String action = getDecodedParam(uri, "action");
String issueId = getDecodedParam(uri, "issueId");

if (!"snyk".equals(scheme)) {
SnykLogger.logInfo(String.format("Invalid URI: expected 'snyk' scheme but got %s", scheme));
} else if (!DIAGNOSTIC_SOURCE_SNYK_CODE.equals(product)) {
SnykLogger.logInfo(String.format("Invalid URI: expected '{}' product but got %s",
DIAGNOSTIC_SOURCE_SNYK_CODE, product));
} else if (!"showInDetailPanel".equals(action)) {
SnykLogger.logInfo(String.format("Invalid URI: expected 'showInDetailPanel' action but got %s", action));
} else if (issueId.isEmpty()) {
SnykLogger.logInfo(String.format("Invalid URI: 'issueId' empty"));
}

if (scheme.equals("snyk") && product.equals(DIAGNOSTIC_SOURCE_SNYK_CODE)

Check warning on line 433 in plugin/src/main/java/io/snyk/languageserver/protocolextension/SnykExtendedLanguageClient.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Position literals first in String comparisons

Position literals first in all String comparisons, if the second argument is null then NullPointerExceptions can be avoided, they will just return false. Note that switching literal positions for compareTo and compareToIgnoreCase may change the result, see examples. LiteralsFirstInComparisons (Priority: 3, Ruleset: Best Practices) https://docs.pmd-code.org/pmd-doc-7.10.0/pmd_rules_java_bestpractices.html#literalsfirstincomparisons

Check warning

Code scanning / PMD

Position literals first in String comparisons Warning

Position literals first in String comparisons
&& action.equals("showInDetailPanel")) {

Check warning on line 434 in plugin/src/main/java/io/snyk/languageserver/protocolextension/SnykExtendedLanguageClient.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Position literals first in String comparisons

Position literals first in all String comparisons, if the second argument is null then NullPointerExceptions can be avoided, they will just return false. Note that switching literal positions for compareTo and compareToIgnoreCase may change the result, see examples. LiteralsFirstInComparisons (Priority: 3, Ruleset: Best Practices) https://docs.pmd-code.org/pmd-doc-7.10.0/pmd_rules_java_bestpractices.html#literalsfirstincomparisons

Check warning

Code scanning / PMD

Position literals first in String comparisons Warning

Position literals first in String comparisons
return CompletableFuture.supplyAsync(() -> {

Issue issue = getIssueFromCache(uri);
this.toolView.selectTreeNode(issue, product);
return new ShowDocumentResult(true);
});
} else {
SnykLogger.logInfo(String.format("Invalid URI: scheme=%s, product=%s, action=%s", scheme, product, action));
return super.showDocument(params);
}
}

public Issue getIssueFromCache(URI uri) {
String filePath = uri.getPath();
String issueId = getDecodedParam(uri, "issueId");

SnykIssueCache issueCache = getIssueCache(filePath);
return issueCache.getCodeSecurityIssuesForPath(filePath).stream().filter(i -> i.id().equals(issueId))
.findFirst().orElse(null);
}

public String getDecodedParam(URI uri, String paramName) {
Map<String, String> paramMap = parseQueryString(uri.getQuery());

try {
return URLDecoder.decode(paramMap.get(paramName), "UTF-8");
} catch (UnsupportedEncodingException e) {
SnykLogger.logError(e);
}
return null;
}

private static Map<String, String> parseQueryString(String queryString) {
Map<String, String> paramMap = new HashMap<>();

for (String param : queryString.split("&")) {
if (!param.isEmpty()) {
String[] keyValue = param.split("=");

if (keyValue.length == 2) {

Check warning on line 474 in plugin/src/main/java/io/snyk/languageserver/protocolextension/SnykExtendedLanguageClient.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Avoid using literals in if statements

Avoid using hard-coded literals in conditional statements. By declaring them as static variables or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored. More exceptions can be defined with the property "ignoreMagicNumbers". The rule doesn't consider deeper expressions by default, but this can be enabled via the property `ignoreExpressions`. With this property set to false, if-conditions like `i == 1 + 5` are reported as well. Note that in that case, the property ignoreMagicNumbers is not taken into account, if there are multiple literals involved in such an expression. AvoidLiteralsInIfCondition (Priority: 3, Ruleset: Error Prone) https://docs.pmd-code.org/pmd-doc-7.10.0/pmd_rules_java_errorprone.html#avoidliteralsinifcondition

Check warning

Code scanning / PMD

Avoid using literals in if statements Warning

Avoid using literals in if statements
try {
paramMap.put(keyValue[0], URLDecoder.decode(keyValue[1], "UTF-8"));
} catch (UnsupportedEncodingException e) {
SnykLogger.logError(e);
}
}
}
}

return paramMap;
}

private void openToolView() {
Expand Down Expand Up @@ -473,7 +561,7 @@ public String getCountsSuffix(ProductTreeNode productTreeNode, SnykIssueCache is
high, medium, low);
}

private SnykIssueCache getIssueCache(String filePath) {
public SnykIssueCache getIssueCache(String filePath) {
var issueCache = IssueCacheHolder.getInstance().getCacheInstance(Paths.get(filePath));
if (issueCache == null) {
throw new IllegalArgumentException("No issue cache for param possible");
Expand Down Expand Up @@ -548,11 +636,11 @@ private void populateFileAndIssueNodes(ProductTreeNode productTreeNode, SnykIssu

if (issuesList.isEmpty())
continue;
FileTreeNode fileNode = new FileTreeNode(fileName); //NOPMD

FileTreeNode fileNode = new FileTreeNode(fileName); // NOPMD
toolView.addFileNode(productTreeNode, fileNode);
for (Issue issue : issuesList) {
toolView.addIssueNode(fileNode, new IssueTreeNode(issue)); //NOPMD
toolView.addIssueNode(fileNode, new IssueTreeNode(issue)); // NOPMD
}
}
}
Expand Down

0 comments on commit 269c2ae

Please sign in to comment.