From 9960aea337ffbc32998ac1ac74b82f1730d536e8 Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Tue, 8 Oct 2024 15:07:05 +0200 Subject: [PATCH 1/8] fix: update required ls version to 16 --- .../snyk/plugin/services/SnykApplicationSettingsStateService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/io/snyk/plugin/services/SnykApplicationSettingsStateService.kt b/src/main/kotlin/io/snyk/plugin/services/SnykApplicationSettingsStateService.kt index 437f07287..98547d86f 100644 --- a/src/main/kotlin/io/snyk/plugin/services/SnykApplicationSettingsStateService.kt +++ b/src/main/kotlin/io/snyk/plugin/services/SnykApplicationSettingsStateService.kt @@ -26,7 +26,7 @@ import java.util.UUID storages = [Storage("snyk.settings.xml", roamingType = RoamingType.DISABLED)], ) class SnykApplicationSettingsStateService : PersistentStateComponent { - val requiredLsProtocolVersion = 15 + val requiredLsProtocolVersion = 16 var useTokenAuthentication = false var currentLSProtocolVersion: Int? = 0 From 1199613fbb0ea4a18ec8ee097c1ffcdf9dcd5a3b Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Tue, 8 Oct 2024 15:07:41 +0200 Subject: [PATCH 2/8] fix: don't refresh ui if project is disposed --- .../kotlin/snyk/common/lsp/LanguageServerBulkFileListener.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/kotlin/snyk/common/lsp/LanguageServerBulkFileListener.kt b/src/main/kotlin/snyk/common/lsp/LanguageServerBulkFileListener.kt index 7b44d7cf2..f33736a7d 100644 --- a/src/main/kotlin/snyk/common/lsp/LanguageServerBulkFileListener.kt +++ b/src/main/kotlin/snyk/common/lsp/LanguageServerBulkFileListener.kt @@ -15,6 +15,7 @@ import io.snyk.plugin.SnykFile import io.snyk.plugin.getSnykCachedResults import io.snyk.plugin.toLanguageServerURL import io.snyk.plugin.toSnykFileSet +import io.snyk.plugin.ui.toolwindow.SnykPluginDisposable import org.eclipse.lsp4j.DidSaveTextDocumentParams import org.eclipse.lsp4j.TextDocumentIdentifier import org.jetbrains.annotations.TestOnly @@ -122,6 +123,7 @@ class LanguageServerBulkFileListener : SnykBulkFileListener() { VirtualFileManager.getInstance().asyncRefresh() invokeLater { + if (SnykPluginDisposable.getInstance(project).isDisposed() || project.isDisposed) return@invokeLater DaemonCodeAnalyzer.getInstance(project).restart() } } From 50bde2208d76f9395f62c4c4ae8054c851025acd Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Tue, 8 Oct 2024 15:08:00 +0200 Subject: [PATCH 3/8] feat: transmit configured jdks to LS --- .../snyk/common/lsp/LanguageServerWrapper.kt | 27 ++++++++++++++++++- src/main/kotlin/snyk/common/lsp/Types.kt | 2 ++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt b/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt index 1268fa44e..cabf18662 100644 --- a/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt +++ b/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt @@ -5,10 +5,14 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectManager +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.toNioPathOrNull import com.intellij.openapi.vfs.VirtualFile import io.snyk.plugin.getCliFile @@ -397,7 +401,8 @@ class LanguageServerWrapper( try { val param = ExecuteCommandParams() param.command = COMMAND_WORKSPACE_FOLDER_SCAN - param.arguments = listOf(folder) + param.arguments = listOf(folder, getSdks(project)) + logger.warn(Gson().toJson(param)) languageServer.workspaceService.executeCommand(param) } catch (e: Exception) { logger.error("error calling scan command from language server. re-initializing", e) @@ -405,6 +410,26 @@ class LanguageServerWrapper( } } + private fun getSdks(project: Project): List { + val list: MutableList = mutableListOf() + val modules = ModuleManager.getInstance(project).modules + for (module in modules) { + val moduleSdk = ModuleRootManager.getInstance(module).sdk + addSdkToList(moduleSdk, list) + } + return list.toList() + } + + private fun addSdkToList( + sdk: Sdk?, + list: MutableList + ) { + if (sdk != null && sdk.homeDirectory != null) { + list.add(LsSdk(sdk.sdkType.name, FileUtil.toSystemDependentName(sdk.homeDirectory!!.path))) + } + } + + private fun restart() { runInBackground("Snyk: restarting language server...") { shutdown() diff --git a/src/main/kotlin/snyk/common/lsp/Types.kt b/src/main/kotlin/snyk/common/lsp/Types.kt index cffbf5f38..095d0863f 100644 --- a/src/main/kotlin/snyk/common/lsp/Types.kt +++ b/src/main/kotlin/snyk/common/lsp/Types.kt @@ -18,6 +18,8 @@ import javax.swing.Icon typealias FilterableIssueType = String +data class LsSdk(val type: String, val path: String) + data class CliError( val code: Int? = 0, val error: String? = null, From d49cab228d3ec1928458d77ff9ea382b7b04a9ed Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Tue, 8 Oct 2024 15:08:47 +0200 Subject: [PATCH 4/8] docs: update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80bab086d..c5fc1ff5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ - add inline value support for display of vulnerability count - added ai fix feedback support - enable for IntelliJ 2024.3 platform +- require LS protocol version 16 +- transmit project sdks to language server ### Fixes - add name to code vision provider From 0bb345277ffd8c7f1cc7a34ba925ebb09506659e Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Tue, 8 Oct 2024 15:19:30 +0200 Subject: [PATCH 5/8] feat: add listener/callback to return the sdks for a workspace folder --- .../snyk/common/lsp/LanguageServerWrapper.kt | 27 +--------------- .../snyk/common/lsp/SnykLanguageClient.kt | 11 +++++++ src/main/kotlin/snyk/sdk/SdkHelper.kt | 31 +++++++++++++++++++ 3 files changed, 43 insertions(+), 26 deletions(-) create mode 100644 src/main/kotlin/snyk/sdk/SdkHelper.kt diff --git a/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt b/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt index cabf18662..1268fa44e 100644 --- a/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt +++ b/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt @@ -5,14 +5,10 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectManager -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.util.Disposer -import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.toNioPathOrNull import com.intellij.openapi.vfs.VirtualFile import io.snyk.plugin.getCliFile @@ -401,8 +397,7 @@ class LanguageServerWrapper( try { val param = ExecuteCommandParams() param.command = COMMAND_WORKSPACE_FOLDER_SCAN - param.arguments = listOf(folder, getSdks(project)) - logger.warn(Gson().toJson(param)) + param.arguments = listOf(folder) languageServer.workspaceService.executeCommand(param) } catch (e: Exception) { logger.error("error calling scan command from language server. re-initializing", e) @@ -410,26 +405,6 @@ class LanguageServerWrapper( } } - private fun getSdks(project: Project): List { - val list: MutableList = mutableListOf() - val modules = ModuleManager.getInstance(project).modules - for (module in modules) { - val moduleSdk = ModuleRootManager.getInstance(module).sdk - addSdkToList(moduleSdk, list) - } - return list.toList() - } - - private fun addSdkToList( - sdk: Sdk?, - list: MutableList - ) { - if (sdk != null && sdk.homeDirectory != null) { - list.add(LsSdk(sdk.sdkType.name, FileUtil.toSystemDependentName(sdk.homeDirectory!!.path))) - } - } - - private fun restart() { runInBackground("Snyk: restarting language server...") { shutdown() diff --git a/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt b/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt index 13a456387..92c16b9ba 100644 --- a/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt +++ b/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt @@ -13,6 +13,7 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectLocator import com.intellij.openapi.project.ProjectManager +import com.intellij.openapi.project.guessProjectForFile import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.toNioPathOrNull import com.intellij.openapi.vfs.VfsUtilCore @@ -35,13 +36,16 @@ import org.eclipse.lsp4j.ProgressParams import org.eclipse.lsp4j.PublishDiagnosticsParams import org.eclipse.lsp4j.ShowMessageRequestParams import org.eclipse.lsp4j.WorkDoneProgressCreateParams +import org.eclipse.lsp4j.WorkspaceFolder import org.eclipse.lsp4j.jsonrpc.services.JsonNotification +import org.eclipse.lsp4j.jsonrpc.services.JsonRequest import org.eclipse.lsp4j.services.LanguageClient import org.jetbrains.concurrency.runAsync import snyk.common.ProductType import snyk.common.editor.DocumentChanger import snyk.common.lsp.progress.ProgressManager import snyk.common.lsp.settings.FolderConfigSettings +import snyk.sdk.SdkHelper import snyk.trust.WorkspaceTrustService import java.util.concurrent.ArrayBlockingQueue import java.util.concurrent.CompletableFuture @@ -278,6 +282,13 @@ class SnykLanguageClient : } } + @JsonRequest(value = "$/snyk.getSDKs") + fun getSdks(workspaceFolder: WorkspaceFolder) : List { + val project = guessProjectForFile(workspaceFolder.uri.toVirtualFile()) ?: return emptyList() + return SdkHelper.getSdks(project) + } + + @JsonNotification(value = "$/snyk.addTrustedFolders") fun addTrustedPaths(param: SnykTrustedFoldersParams) { if (disposed) return diff --git a/src/main/kotlin/snyk/sdk/SdkHelper.kt b/src/main/kotlin/snyk/sdk/SdkHelper.kt new file mode 100644 index 000000000..cacd2fdcc --- /dev/null +++ b/src/main/kotlin/snyk/sdk/SdkHelper.kt @@ -0,0 +1,31 @@ +package snyk.sdk + +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.util.io.FileUtil +import snyk.common.lsp.LsSdk + +class SdkHelper { + companion object { + fun getSdks(project: Project): List { + val list: MutableList = mutableListOf() + val modules = ModuleManager.getInstance(project).modules + for (module in modules) { + val moduleSdk = ModuleRootManager.getInstance(module).sdk + addSdkToList(moduleSdk, list) + } + return list.toList() + } + + private fun addSdkToList( + sdk: Sdk?, + list: MutableList + ) { + if (sdk != null && sdk.homeDirectory != null) { + list.add(LsSdk(sdk.sdkType.name, FileUtil.toSystemDependentName(sdk.homeDirectory!!.path))) + } + } + } +} From 1a388587df350106474380948322a49909bf4a73 Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Tue, 8 Oct 2024 17:46:04 +0200 Subject: [PATCH 6/8] feat: add get sdks callback listener --- CHANGELOG.md | 2 +- src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5fc1ff5f..d53372a21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ - added ai fix feedback support - enable for IntelliJ 2024.3 platform - require LS protocol version 16 -- transmit project sdks to language server +- transmit project sdks to language server when requested by a scan ### Fixes - add name to code vision provider diff --git a/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt b/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt index 92c16b9ba..d9df12bf8 100644 --- a/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt +++ b/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt @@ -282,10 +282,10 @@ class SnykLanguageClient : } } - @JsonRequest(value = "$/snyk.getSDKs") - fun getSdks(workspaceFolder: WorkspaceFolder) : List { - val project = guessProjectForFile(workspaceFolder.uri.toVirtualFile()) ?: return emptyList() - return SdkHelper.getSdks(project) + @JsonRequest(value = "workspace/snyk.sdks") + fun getSdks(workspaceFolder: WorkspaceFolder) : CompletableFuture> { + val project = guessProjectForFile(workspaceFolder.uri.toVirtualFile()) ?: return CompletableFuture.completedFuture(emptyList()) + return CompletableFuture.completedFuture(SdkHelper.getSdks(project)) } From 8999eba004a2dec7cdcb37d03588edcc613a7d16 Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Thu, 10 Oct 2024 08:17:49 +0200 Subject: [PATCH 7/8] fix: test that needed release info while it shouldn't --- .../plugin/services/download/CliDownloaderServiceIntegTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/kotlin/io/snyk/plugin/services/download/CliDownloaderServiceIntegTest.kt b/src/test/kotlin/io/snyk/plugin/services/download/CliDownloaderServiceIntegTest.kt index 771b64a4d..a06f46276 100644 --- a/src/test/kotlin/io/snyk/plugin/services/download/CliDownloaderServiceIntegTest.kt +++ b/src/test/kotlin/io/snyk/plugin/services/download/CliDownloaderServiceIntegTest.kt @@ -131,6 +131,7 @@ class CliDownloaderServiceIntegTest : LightPlatformTestCase() { fun testDownloadLatestCliReleaseShouldHandleHttpStatusException() { val httpStatusException = HttpRequests.HttpStatusException("status bad", HttpStatus.SC_GATEWAY_TIMEOUT, "url") + every { cutSpy.requestLatestReleasesInformation() } returns "1.1294.0" every { downloader.downloadFile(any(), any(), any()) } throws httpStatusException justRun { errorHandler.handleHttpStatusException(httpStatusException, project) } From 709e770ffdb052fa49f3e45c5eeea4dd69cbff6a Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Thu, 10 Oct 2024 08:51:11 +0200 Subject: [PATCH 8/8] chore: add javadoc to download test that's failing When new preview release is available for the required LS protocol version it will fail. This is expected. --- .../plugin/services/download/CliDownloaderServiceIntegTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/kotlin/io/snyk/plugin/services/download/CliDownloaderServiceIntegTest.kt b/src/test/kotlin/io/snyk/plugin/services/download/CliDownloaderServiceIntegTest.kt index a06f46276..118865e57 100644 --- a/src/test/kotlin/io/snyk/plugin/services/download/CliDownloaderServiceIntegTest.kt +++ b/src/test/kotlin/io/snyk/plugin/services/download/CliDownloaderServiceIntegTest.kt @@ -72,7 +72,8 @@ class CliDownloaderServiceIntegTest : LightPlatformTestCase() { /** * Should be THE ONLY test where we actually do download the CLI - * !!! Do __MOCK__ cli download in ANY other test to reduce testing time needed !!! + * 🚨 Do __MOCK__ cli download in ANY other test to reduce testing time needed !!! + * 🚨 This test fails when the preview release is not available yet */ fun testDownloadLatestCliRelease() { ensureCliFileExistent()