Skip to content

Commit

Permalink
fix: don't double scan on startup, handle feature flags better (#618)
Browse files Browse the repository at this point in the history
* feat: auto-detect consistent ignores from issue

* fix: only scan once on startup, check for token existence before ops

* refactor: small changes with feature flags

* fix: initialization bug, code vision

* fix: settings dialog issue view options refresh and scan errors

* chore: remove ignored test

* fix: tests now add token to account for additional check

* fix: dont initialize language server with workspace folders.

when opening a project, the project startup activity is registering all content roots.

* chore: remove unused code

* chore: display progresses for some async actions

* chore: remove unused imports

* fix: improve feature flag retrieval and start up
  • Loading branch information
bastiandoetsch authored Oct 7, 2024
1 parent 14e0a29 commit 3ac2828
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 147 deletions.
2 changes: 1 addition & 1 deletion src/main/kotlin/io/snyk/plugin/SnykPostStartupActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class SnykPostStartupActivity : ProjectActivity {
}

if (!settings.token.isNullOrBlank() && settings.scanOnSave) {
getSnykTaskQueueService(project)?.scan()
getSnykTaskQueueService(project)?.scheduleContainerScan()
}

ExtensionPointsUtil.controllerManager.extensionList.forEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class SnykProjectManagerListener : ProjectManagerListener {
val threadPool: ExecutorService = Executors.newWorkStealingPool()

override fun projectClosing(project: Project) {
val closingTask = object : Backgroundable(project, "Project closing ${project.name}") {
val closingTask = object : Backgroundable(project, "Snyk: Project closing ${project.name}") {
override fun run(indicator: ProgressIndicator) {
// limit clean up to TIMEOUT
try {
Expand Down
10 changes: 10 additions & 0 deletions src/main/kotlin/io/snyk/plugin/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.options.ShowSettingsUtil
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.roots.ProjectFileIndex
Expand Down Expand Up @@ -455,3 +457,11 @@ fun VirtualFile.isInContent(project: Project): Boolean {
val vf = this
return ReadAction.compute<Boolean, RuntimeException> { ProjectFileIndex.getInstance(project).isInContent(vf) }
}

inline fun runInBackground(title: String, project: Project? = null, cancellable: Boolean = true, crossinline task: (indicator: ProgressIndicator) -> Unit) {
ProgressManager.getInstance().run(object : Task.Backgroundable(project, title, cancellable) {
override fun run(indicator: ProgressIndicator) {
task(indicator)
}
})
}
26 changes: 7 additions & 19 deletions src/main/kotlin/io/snyk/plugin/services/SnykTaskQueueService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.progress.BackgroundTaskQueue
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import io.snyk.plugin.events.SnykCliDownloadListener
import io.snyk.plugin.events.SnykScanListener
import io.snyk.plugin.events.SnykSettingsListener
import io.snyk.plugin.events.SnykTaskQueueListener
import io.snyk.plugin.getContainerService
import io.snyk.plugin.getSnykCachedResults
import io.snyk.plugin.getSnykCliDownloaderService
import io.snyk.plugin.getSnykToolWindowPanel
import io.snyk.plugin.getSyncPublisher
import io.snyk.plugin.isCliDownloading
import io.snyk.plugin.isCliInstalled
Expand Down Expand Up @@ -52,23 +51,13 @@ class SnykTaskQueueService(val project: Project) {
fun getTaskQueue() = taskQueue

fun connectProjectToLanguageServer(project: Project) {
// subscribe to the settings changed topic
val languageServerWrapper = LanguageServerWrapper.getInstance()
languageServerWrapper.ensureLanguageServerInitialized()

getSnykToolWindowPanel(project)?.let {
project.messageBus.connect(it)
.subscribe(
SnykSettingsListener.SNYK_SETTINGS_TOPIC,
object : SnykSettingsListener {
override fun settingsChanged() {
languageServerWrapper.updateConfiguration()
}
}
)
// wait for modules to be loaded and indexed so we can add all relevant content roots
DumbService.getInstance(project).runWhenSmart {
languageServerWrapper.addContentRoots(project)
}

languageServerWrapper.addContentRoots(project)
}

fun scan() {
Expand All @@ -85,9 +74,7 @@ class SnykTaskQueueService(val project: Project) {

LanguageServerWrapper.getInstance().sendScanCommand(project)

if (settings.containerScanEnabled) {
scheduleContainerScan()
}
scheduleContainerScan()
}
})
}
Expand All @@ -99,7 +86,8 @@ class SnykTaskQueueService(val project: Project) {
} while (isCliDownloading())
}

private fun scheduleContainerScan() {
fun scheduleContainerScan() {
if (!settings.containerScanEnabled) return
taskQueueContainer.run(object : Task.Backgroundable(project, "Snyk Container is scanning...", true) {
override fun run(indicator: ProgressIndicator) {
if (!isCliInstalled()) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,7 @@ class SnykProjectSettingsConfigurable(
}

runBackgroundableTask("processing config changes", project, true) {
settingsStateService.isGlobalIgnoresFeatureEnabled =
LanguageServerWrapper.getInstance().isGlobalIgnoresFeatureEnabled()


val languageServerWrapper = LanguageServerWrapper.getInstance()
if (snykSettingsDialog.getCliReleaseChannel().trim() != pluginSettings().cliReleaseChannel) {
handleReleaseChannelChanged()
}
Expand All @@ -128,7 +125,8 @@ class SnykProjectSettingsConfigurable(
getSnykToolWindowPanel(project)?.getTree()?.isRootVisible = pluginSettings().isDeltaFindingsEnabled()
}

LanguageServerWrapper.getInstance().updateConfiguration()
languageServerWrapper.refreshFeatureFlags()
languageServerWrapper.updateConfiguration()
}

if (rescanNeeded) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.ui.ValidationInfo
import com.intellij.util.ui.GridBag
import com.intellij.util.ui.JBUI
import org.jetbrains.concurrency.runAsync
import io.snyk.plugin.runInBackground
import snyk.common.lsp.FolderConfig
import snyk.common.lsp.settings.FolderConfigSettings
import snyk.common.lsp.LanguageServerWrapper
import snyk.common.lsp.settings.FolderConfigSettings
import java.awt.GridBagConstraints
import java.awt.GridBagLayout
import javax.swing.JComponent
Expand Down Expand Up @@ -66,7 +66,7 @@ class BranchChooserComboBoxDialog(val project: Project) : DialogWrapper(true) {
val baseBranch = it.selectedItem!!.toString() // validation makes sure it is not null and not empty
folderConfigSettings.addFolderConfig(folderConfig.copy(baseBranch = baseBranch))
}
runAsync {
runInBackground("Snyk: updating configuration") {
LanguageServerWrapper.getInstance().updateConfiguration()
}
}
Expand Down
74 changes: 41 additions & 33 deletions src/main/kotlin/io/snyk/plugin/ui/SnykSettingsDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ import io.snyk.plugin.ui.settings.IssueViewOptionsPanel
import io.snyk.plugin.ui.settings.ScanTypesPanel
import io.snyk.plugin.ui.settings.SeveritiesEnablementPanel
import io.snyk.plugin.ui.toolwindow.SnykPluginDisposable
import org.jetbrains.concurrency.runAsync
import snyk.SnykBundle
import snyk.common.lsp.LanguageServerWrapper
import snyk.common.lsp.settings.FolderConfigSettings
import java.awt.GridBagConstraints
import java.awt.GridBagLayout
Expand Down Expand Up @@ -376,41 +378,47 @@ class SnykSettingsDialog(

/** Products and Severities selection ------------------ */

if (pluginSettings().isGlobalIgnoresFeatureEnabled) {
val issueViewPanel = JPanel(UIGridLayoutManager(3, 2, JBUI.emptyInsets(), 30, -1))
issueViewPanel.border = IdeBorderFactory.createTitledBorder("Issue view options")
val issueViewPanel = JPanel(UIGridLayoutManager(3, 2, JBUI.emptyInsets(), 30, -1))
issueViewPanel.isVisible = true
issueViewPanel.border = IdeBorderFactory.createTitledBorder("Issue view options")

val issueViewLabel = JLabel("Show the following issues:")
issueViewPanel.add(
issueViewLabel,
baseGridConstraintsAnchorWest(
row = 0,
indent = 0,
),
)
val issueViewLabel = JLabel("Show the following issues:")
issueViewPanel.add(
issueViewLabel,
baseGridConstraintsAnchorWest(
row = 0,
indent = 0,
),
)

rootPanel.add(
issueViewPanel,
baseGridConstraints(
row = 1,
anchor = UIGridConstraints.ANCHOR_NORTHWEST,
fill = UIGridConstraints.FILL_HORIZONTAL,
hSizePolicy = UIGridConstraints.SIZEPOLICY_CAN_SHRINK or UIGridConstraints.SIZEPOLICY_CAN_GROW,
indent = 0,
),
)
rootPanel.add(
issueViewPanel,
baseGridConstraints(
row = 1,
anchor = UIGridConstraints.ANCHOR_NORTHWEST,
fill = UIGridConstraints.FILL_HORIZONTAL,
hSizePolicy = UIGridConstraints.SIZEPOLICY_CAN_SHRINK or UIGridConstraints.SIZEPOLICY_CAN_GROW,
indent = 0,
),
)

issueViewPanel.add(
this.issueViewOptionsPanel,
baseGridConstraints(
row = 1,
anchor = UIGridConstraints.ANCHOR_NORTHWEST,
fill = UIGridConstraints.FILL_NONE,
hSizePolicy = UIGridConstraints.SIZEPOLICY_CAN_SHRINK or UIGridConstraints.SIZEPOLICY_CAN_GROW,
vSizePolicy = UIGridConstraints.SIZEPOLICY_CAN_SHRINK or UIGridConstraints.SIZEPOLICY_CAN_GROW,
indent = 0,
),
)
issueViewPanel.add(
this.issueViewOptionsPanel,
baseGridConstraints(
row = 1,
anchor = UIGridConstraints.ANCHOR_NORTHWEST,
fill = UIGridConstraints.FILL_NONE,
hSizePolicy = UIGridConstraints.SIZEPOLICY_CAN_SHRINK or UIGridConstraints.SIZEPOLICY_CAN_GROW,
vSizePolicy = UIGridConstraints.SIZEPOLICY_CAN_SHRINK or UIGridConstraints.SIZEPOLICY_CAN_GROW,
indent = 0,
),
)

runAsync {
if (!pluginSettings().isGlobalIgnoresFeatureEnabled) {
LanguageServerWrapper.getInstance().refreshFeatureFlags()
}
issueViewPanel.isVisible = pluginSettings().isGlobalIgnoresFeatureEnabled
}

val productAndSeveritiesPanel = JPanel(UIGridLayoutManager(2, 2, JBUI.emptyInsets(), 30, -1))
Expand Down Expand Up @@ -605,7 +613,7 @@ class SnykSettingsDialog(
val netNewIssuesText =
JLabel(
"Specifies whether to see only net new issues or all issues. " +
"Only applies to Code Security and Code Quality."
"Only applies to Code Security and Code Quality."
).apply { font = FontUtil.minusOne(this.font) }

netNewIssuesPanel.add(
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/io/snyk/plugin/ui/jcef/ApplyFixHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import com.intellij.openapi.project.Project
import com.intellij.ui.jcef.JBCefBrowserBase
import com.intellij.ui.jcef.JBCefJSQuery
import io.snyk.plugin.DiffPatcher
import io.snyk.plugin.runInBackground
import io.snyk.plugin.toVirtualFile
import io.snyk.plugin.ui.SnykBalloonNotificationHelper
import org.cef.browser.CefBrowser
import org.cef.browser.CefFrame
import org.cef.handler.CefLoadHandlerAdapter
import org.jetbrains.concurrency.runAsync
import io.snyk.plugin.ui.SnykBalloonNotificationHelper
import snyk.common.lsp.LanguageServerWrapper
import java.io.IOException

Expand All @@ -36,7 +36,7 @@ class ApplyFixHandler(private val project: Project) {
val patch = params[2] // The patch we received from LS

// Avoid blocking the UI thread
runAsync {
runInBackground("Snyk: applying fix...") {
val result = try {
applyPatchAndSave(project, filePath, patch)
} catch (e: IOException) { // Catch specific file-related exceptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package io.snyk.plugin.ui.jcef
import com.google.gson.Gson
import com.intellij.ui.jcef.JBCefBrowserBase
import com.intellij.ui.jcef.JBCefJSQuery
import io.snyk.plugin.runInBackground
import org.cef.browser.CefBrowser
import org.cef.browser.CefFrame
import org.cef.handler.CefLoadHandlerAdapter
import org.jetbrains.concurrency.runAsync
import snyk.common.lsp.LanguageServerWrapper
import snyk.common.lsp.Fix
import snyk.common.lsp.LanguageServerWrapper


class GenerateAIFixHandler() {
Expand All @@ -23,7 +23,7 @@ class GenerateAIFixHandler() {
val issueID = params[2]


runAsync {
runInBackground("Snyk: getting AI fix proposals...") {
val responseDiff: List<Fix> =
LanguageServerWrapper.getInstance().sendCodeFixDiffsCommand(folderURI, fileURI, issueID)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ class LSCodeVisionProvider : CodeVisionProvider<Unit>, CodeVisionGroupSettingPro
if (LanguageServerWrapper.getInstance().isDisposed()) return CodeVisionState.READY_EMPTY
if (!LanguageServerWrapper.getInstance().isInitialized) return CodeVisionState.READY_EMPTY
val project = editor.project ?: return CodeVisionState.READY_EMPTY
if (!editor.virtualFile.isInContent(project)) return CodeVisionState.READY_EMPTY

val document = editor.document

val file = ReadAction.compute<PsiFile, RuntimeException> {
PsiDocumentManager.getInstance(project).getPsiFile(document)
} ?: return CodeVisionState.READY_EMPTY

val virtualFile = file.virtualFile
if (!virtualFile.isInContent(project)) return CodeVisionState.READY_EMPTY

val params = CodeLensParams(TextDocumentIdentifier(file.virtualFile.toLanguageServerURL()))
val lenses = mutableListOf<Pair<TextRange, CodeVisionEntry>>()
Expand Down
Loading

0 comments on commit 3ac2828

Please sign in to comment.