Skip to content

Commit

Permalink
Merge pull request #645 from snyk/fix/workspaceFolder_not_configured
Browse files Browse the repository at this point in the history
fix: only scan workspace folder, if folder is known to language server
  • Loading branch information
bastiandoetsch authored Jan 8, 2025
2 parents 72b9df7 + 97bc793 commit 9ca313c
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 14 deletions.
1 change: 1 addition & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ db2662b39d5195aeda376109d21d1530c194711e:src/main/scala/io/snyk/plugin/client/Ap
372778ad27f3293b03c96eed86dccfe4d6d8c6f4:src/main/scala/io/snyk/plugin/ApiClient.scala:generic-api-key:14
372778ad27f3293b03c96eed86dccfe4d6d8c6f4:src/main/scala/io/snyk/plugin/ApiClient.scala:generic-api-key:17
372778ad27f3293b03c96eed86dccfe4d6d8c6f4:src/main/scala/io/snyk/plugin/ApiClient.scala:generic-api-key:20
67244ecb074381e16902870e29d9f734cc611fd8:src/main/scala/io/snyk/plugin/metrics/SegmentApi.scala:generic-api-key:56
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Added a description of custom endpoints to settings dialog.
- Add option to ignore IaC issues
### Fixed
- only ask to scan folders that are known to language server
- folder-specific configs are availabe on opening projects, not only on restart of the IDE
- display open source issues in Rider. Previously, as the project.assets.json is in a derived folder, it was filtered.
- correctly display and update base branch name for Net New Issues
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class SnykProjectManagerListener : ProjectManagerListener {
threadPool.submit {
val ls = LanguageServerWrapper.getInstance()
if (ls.isInitialized) {
ls.updateWorkspaceFolders(emptySet(), ls.getWorkspaceFolders(project))
ls.updateWorkspaceFolders(emptySet(), ls.getWorkspaceFoldersFromRoots(project))
}
}.get(TIMEOUT, TimeUnit.SECONDS)
} catch (ignored: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class SnykCliAuthenticationService(
if (getCliFile().exists()) {
executeAuthCommand()
}
LanguageServerWrapper.getInstance().updateConfiguration()
LanguageServerWrapper.getInstance().updateConfiguration(false)
}

private fun downloadCliIfNeeded() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import io.snyk.plugin.isUrlValid
import io.snyk.plugin.pluginSettings
import io.snyk.plugin.ui.SnykBalloonNotificationHelper
import io.snyk.plugin.ui.SnykSettingsDialog
import snyk.common.lsp.settings.FolderConfigSettings
import snyk.common.lsp.LanguageServerWrapper
import snyk.common.lsp.settings.FolderConfigSettings
import javax.swing.JComponent

class SnykProjectSettingsConfigurable(
Expand Down Expand Up @@ -126,7 +126,7 @@ class SnykProjectSettingsConfigurable(
}

languageServerWrapper.refreshFeatureFlags()
languageServerWrapper.updateConfiguration()
languageServerWrapper.updateConfiguration(true)
}

if (rescanNeeded) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class BranchChooserComboBoxDialog(val project: Project) : DialogWrapper(true) {
folderConfigSettings.addFolderConfig(folderConfig.copy(baseBranch = baseBranch))
}
runInBackground("Snyk: updating configuration") {
LanguageServerWrapper.getInstance().updateConfiguration()
LanguageServerWrapper.getInstance().updateConfiguration(true)
}
}

Expand Down
33 changes: 26 additions & 7 deletions src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,14 @@ import snyk.common.lsp.commands.SNYK_GENERATE_ISSUE_DESCRIPTION
import snyk.common.lsp.progress.ProgressManager
import snyk.common.lsp.settings.LanguageServerSettings
import snyk.common.lsp.settings.SeverityFilter
import snyk.common.removeTrailingSlashesIfPresent
import snyk.pluginInfo
import snyk.trust.WorkspaceTrustService
import snyk.trust.confirmScanningAndSetWorkspaceTrustedStateIfNeeded
import java.io.FileNotFoundException
import java.net.URI
import java.nio.file.Paths
import java.util.Collections
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
Expand All @@ -85,6 +90,8 @@ class LanguageServerWrapper(
private var authenticatedUser: Map<String, String>? = null
private var initializeResult: InitializeResult? = null
private val gson = Gson()
// internal for test set up
internal val configuredWorkspaceFolders: MutableSet<WorkspaceFolder> = Collections.synchronizedSet(mutableSetOf())
private var disposed = false
get() {
return ApplicationManager.getApplication().isDisposed || field
Expand Down Expand Up @@ -231,7 +238,7 @@ class LanguageServerWrapper(

private fun lsIsAlive() = ::process.isInitialized && process.isAlive

fun getWorkspaceFolders(project: Project): Set<WorkspaceFolder> {
fun getWorkspaceFoldersFromRoots(project: Project): Set<WorkspaceFolder> {
if (disposed || project.isDisposed) return emptySet()
val normalizedRoots = getTrustedContentRoots(project)
return normalizedRoots.map { WorkspaceFolder(it.toLanguageServerURL(), it.name) }.toSet()
Expand Down Expand Up @@ -316,8 +323,15 @@ class LanguageServerWrapper(
try {
if (!ensureLanguageServerInitialized()) return
val params = DidChangeWorkspaceFoldersParams()
params.event = WorkspaceFoldersChangeEvent(added.toList(), removed.toList())
languageServer.workspaceService.didChangeWorkspaceFolders(params)
params.event = WorkspaceFoldersChangeEvent(
added.filter { !configuredWorkspaceFolders.contains(it) },
removed.filter { configuredWorkspaceFolders.contains(it) },
)
if (params.event.added.size > 0 || params.event.removed.size > 0) {
languageServer.workspaceService.didChangeWorkspaceFolders(params)
configuredWorkspaceFolders.removeAll(removed)
configuredWorkspaceFolders.addAll(added)
}
} catch (e: Exception) {
logger.error(e)
}
Expand Down Expand Up @@ -365,6 +379,7 @@ class LanguageServerWrapper(
if (notAuthenticated()) return
DumbService.getInstance(project).runWhenSmart {
getTrustedContentRoots(project).forEach {
addContentRoots(project)
sendFolderScanCommand(it.path, project)
}
}
Expand Down Expand Up @@ -424,10 +439,14 @@ class LanguageServerWrapper(
if (notAuthenticated()) return
if (DumbService.getInstance(project).isDumb) return
try {
val folderUri = Paths.get(folder).toUri().toASCIIString().removeTrailingSlashesIfPresent()
if (!configuredWorkspaceFolders.any { it.uri.removeTrailingSlashesIfPresent() == folderUri }) return
val param = ExecuteCommandParams()
param.command = COMMAND_WORKSPACE_FOLDER_SCAN
param.arguments = listOf(folder)
languageServer.workspaceService.executeCommand(param)
} catch (e: FileNotFoundException) {
logger.debug("File not found: $folder")
} catch (e: Exception) {
logger.error("error calling scan command from language server. re-initializing", e)
restart()
Expand Down Expand Up @@ -477,12 +496,12 @@ class LanguageServerWrapper(
)
}

fun updateConfiguration() {
fun updateConfiguration(runScan: Boolean = false) {
if (!ensureLanguageServerInitialized()) return
val params = DidChangeConfigurationParams(getSettings())
languageServer.workspaceService.didChangeConfiguration(params)

if (pluginSettings().scanOnSave) {
if (runScan && pluginSettings().scanOnSave) {
ProjectManager.getInstance().openProjects.forEach { sendScanCommand(it) }
}
}
Expand Down Expand Up @@ -576,8 +595,8 @@ class LanguageServerWrapper(
if (disposed || project.isDisposed) return
ensureLanguageServerInitialized()
ensureLanguageServerProtocolVersion(project)
updateConfiguration()
val added = getWorkspaceFolders(project)
updateConfiguration(false)
val added = getWorkspaceFoldersFromRoots(project)
updateWorkspaceFolders(added, emptySet())
}

Expand Down
9 changes: 7 additions & 2 deletions src/test/kotlin/snyk/common/lsp/LanguageServerWrapperTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import junit.framework.TestCase.fail
import org.eclipse.lsp4j.DidChangeConfigurationParams
import org.eclipse.lsp4j.ExecuteCommandParams
import org.eclipse.lsp4j.InitializeParams
import org.eclipse.lsp4j.WorkspaceFolder
import org.eclipse.lsp4j.services.LanguageServer
import org.junit.After
import org.junit.Before
Expand All @@ -31,6 +32,7 @@ import snyk.common.lsp.analytics.ScanDoneEvent
import snyk.common.lsp.settings.FolderConfigSettings
import snyk.pluginInfo
import snyk.trust.WorkspaceTrustService
import java.nio.file.Paths
import java.util.concurrent.CompletableFuture

class LanguageServerWrapperTest {
Expand Down Expand Up @@ -218,7 +220,10 @@ class LanguageServerWrapperTest {
lsMock.workspaceService.executeCommand(any<ExecuteCommandParams>())
} returns CompletableFuture.completedFuture(null)

cut.sendFolderScanCommand("testFolder", projectMock)
val folder = "testFolder"
cut.configuredWorkspaceFolders.add(WorkspaceFolder(Paths.get(folder).toUri().toASCIIString(), folder))

cut.sendFolderScanCommand(folder, projectMock)

verify { lsMock.workspaceService.executeCommand(any<ExecuteCommandParams>()) }
}
Expand Down Expand Up @@ -263,7 +268,7 @@ class LanguageServerWrapperTest {
every { dumbServiceMock.isDumb } returns false
settings.scanOnSave = true

cut.updateConfiguration()
cut.updateConfiguration(true)

verify { lsMock.workspaceService.didChangeConfiguration(any<DidChangeConfigurationParams>()) }

Expand Down

0 comments on commit 9ca313c

Please sign in to comment.