Skip to content

Commit

Permalink
Merge pull request #616 from snyk/feat/iac-from-ls
Browse files Browse the repository at this point in the history
feat: source IaC results from LS, make progresses & scans cancelable [IDE-630]
  • Loading branch information
bastiandoetsch authored Oct 2, 2024
2 parents fd79a41 + 602cf96 commit 14e0a29
Show file tree
Hide file tree
Showing 76 changed files with 1,081 additions and 2,578 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Snyk Security Changelog


## [2.10.0]
### Changed
- save git folder config in settings
Expand All @@ -18,7 +17,9 @@
- always display info nodes
- add option in IntelliJ registry to display tooltips with issue information
- display documentation info when hovering over issue
- add inline value support for display of vulnerability count
- added ai fix feedback support
- enable for IntelliJ 2024.3 platform

### Fixes
- add name to code vision provider
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pluginName=Snyk Security
# for insight into build numbers and IntelliJ Platform versions
# see https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild=233
pluginUntilBuild=242.*
pluginUntilBuild=243.*
platformVersion=2023.3
platformDownloadSources=true

Expand Down
1 change: 0 additions & 1 deletion src/main/kotlin/io/snyk/plugin/SnykBulkFileListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent
* - addressed at `before` state, old file processed to _clean_ caches
*/
abstract class SnykBulkFileListener : BulkFileListener {

/****************************** Before **************************/

override fun before(events: List<VFileEvent>) {
Expand Down
9 changes: 6 additions & 3 deletions src/main/kotlin/io/snyk/plugin/SnykFile.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package io.snyk.plugin

import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Iconable
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.concurrency.runAsync
import snyk.common.RelativePathHelper
import javax.swing.Icon

data class SnykFile(val project: Project, val virtualFile: VirtualFile) {
val relativePath = RelativePathHelper().getRelativePath(virtualFile, project)
val relativePath = runAsync { RelativePathHelper().getRelativePath(virtualFile, project) }

fun isInContent(): Boolean {
return this.virtualFile.isInContent(project)
}
}

fun toSnykFileSet(project: Project, virtualFiles: Set<VirtualFile>) =
Expand Down
11 changes: 2 additions & 9 deletions src/main/kotlin/io/snyk/plugin/SnykPostStartupActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,21 @@ import com.intellij.ide.plugins.PluginInstaller
import com.intellij.ide.plugins.PluginStateListener
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.startup.ProjectActivity
import com.intellij.openapi.vfs.VirtualFileManager
import io.snyk.plugin.extensions.SnykControllerImpl
import io.snyk.plugin.extensions.SnykControllerManager
import io.snyk.plugin.snykcode.SnykCodeBulkFileListener
import io.snyk.plugin.ui.SnykBalloonNotifications
import snyk.common.AnnotatorCommon
import snyk.common.lsp.LanguageServerBulkFileListener
import snyk.container.ContainerBulkFileListener
import snyk.iac.IacBulkFileListener
import snyk.oss.OssBulkFileListener
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.Date

private val LOG = logger<SnykPostStartupActivity>()

private const val EXTENSION_POINT_CONTROLLER_MANAGER = "io.snyk.snyk-intellij-plugin.controllerManager"

class SnykPostStartupActivity : ProjectActivity {
Expand All @@ -46,9 +41,7 @@ class SnykPostStartupActivity : ProjectActivity {
if (!listenersActivated) {
val messageBusConnection = ApplicationManager.getApplication().messageBus.connect()
// TODO: add subscription for language server messages
messageBusConnection.subscribe(VirtualFileManager.VFS_CHANGES, OssBulkFileListener())
messageBusConnection.subscribe(VirtualFileManager.VFS_CHANGES, SnykCodeBulkFileListener())
messageBusConnection.subscribe(VirtualFileManager.VFS_CHANGES, IacBulkFileListener())
messageBusConnection.subscribe(VirtualFileManager.VFS_CHANGES, LanguageServerBulkFileListener())
messageBusConnection.subscribe(VirtualFileManager.VFS_CHANGES, ContainerBulkFileListener())
messageBusConnection.subscribe(ProjectManager.TOPIC, SnykProjectManagerListener())
listenersActivated = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class SnykProjectManagerListener : ProjectManagerListener {
// limit clean up to TIMEOUT
try {
threadPool.submit {
// lets all running ProgressIndicators release MUTEX first
val ls = LanguageServerWrapper.getInstance()
if (ls.isInitialized) {
ls.updateWorkspaceFolders(emptySet(), ls.getWorkspaceFolders(project))
Expand Down
59 changes: 37 additions & 22 deletions src/main/kotlin/io/snyk/plugin/Utils.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@file:JvmName("UtilsKt")
@file:Suppress("unused")

package io.snyk.plugin

Expand All @@ -19,6 +20,7 @@ import com.intellij.openapi.options.ShowSettingsUtil
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.openapi.util.registry.Registry
Expand Down Expand Up @@ -157,37 +159,43 @@ fun isUrlValid(url: String?): Boolean {
}

fun isOssRunning(project: Project): Boolean {
val lsRunning = project.getContentRootVirtualFiles().any { vf ->
val key = ScanInProgressKey(vf, ProductType.OSS)
ScanState.scanInProgress[key] == true
}
val indicator = getSnykTaskQueueService(project)?.ossScanProgressIndicator
return lsRunning ||
(indicator != null && indicator.isRunning && !indicator.isCanceled)
return isProductScanRunning(project, ProductType.OSS)
}

fun cancelOssIndicator(project: Project) {
val indicator = getSnykTaskQueueService(project)?.ossScanProgressIndicator
indicator?.cancel()
private fun isProductScanRunning(project: Project, productType: ProductType): Boolean {
return isProductScanRunning(project, productType, null)
}

fun isSnykCodeRunning(project: Project): Boolean {
private fun isProductScanRunning(
project: Project,
productType: ProductType,
progressIndicator: ProgressIndicator?
): Boolean {
val lsRunning = project.getContentRootVirtualFiles().any { vf ->
val key = ScanInProgressKey(vf, ProductType.CODE_SECURITY)
val key = ScanInProgressKey(vf, productType)
ScanState.scanInProgress[key] == true
}
return lsRunning ||
(progressIndicator != null && progressIndicator.isRunning && !progressIndicator.isCanceled)
}

return lsRunning
fun isSnykCodeRunning(project: Project): Boolean {
return isProductScanRunning(project, ProductType.CODE_SECURITY) || isProductScanRunning(
project,
ProductType.CODE_QUALITY
)
}

fun isIacRunning(project: Project): Boolean {
val indicator = getSnykTaskQueueService(project)?.iacScanProgressIndicator
return indicator != null && indicator.isRunning && !indicator.isCanceled
return isProductScanRunning(project, ProductType.IAC)
}

fun isContainerRunning(project: Project): Boolean {
val indicator = getSnykTaskQueueService(project)?.containerScanProgressIndicator
return indicator != null && indicator.isRunning && !indicator.isCanceled
return isProductScanRunning(
project,
ProductType.CONTAINER,
getSnykTaskQueueService(project)?.containerScanProgressIndicator
)
}

fun isScanRunning(project: Project): Boolean =
Expand Down Expand Up @@ -215,11 +223,10 @@ fun controlExternalProcessWithProgressIndicator(

fun isFileListenerEnabled(): Boolean = pluginSettings().fileListenerEnabled

fun isSnykIaCLSEnabled(): Boolean = false


fun isDocumentationHoverEnabled(): Boolean = Registry.get("snyk.isDocumentationHoverEnabled").asBoolean()

fun isPreCommitCheckEnabled(): Boolean = Registry.get("snyk.issuesBlockCommit").asBoolean()

fun getWaitForResultsTimeout(): Long =
Registry.intValue(
"snyk.timeout.results.waiting",
Expand All @@ -235,7 +242,7 @@ fun findPsiFileIgnoringExceptions(virtualFile: VirtualFile, project: Project): P
null
} else {
try {
var psiFile : PsiFile? = null
var psiFile: PsiFile? = null
ReadAction.run<RuntimeException> {
psiFile = PsiManager.getInstance(project).findFile(virtualFile)
}
Expand All @@ -262,7 +269,9 @@ fun refreshAnnotationsForOpenFiles(project: Project) {
val psiFile = findPsiFileIgnoringExceptions(it, project)
if (psiFile != null) {
invokeLater {
DaemonCodeAnalyzer.getInstance(project).restart(psiFile)
if (!psiFile.project.isDisposed) {
DaemonCodeAnalyzer.getInstance(project).restart(psiFile)
}
}
}
}
Expand Down Expand Up @@ -427,6 +436,7 @@ fun Project.getContentRootPaths(): SortedSet<Path> {
}

fun Project.getContentRootVirtualFiles(): Set<VirtualFile> {
if (this.isDisposed) return emptySet()
var contentRoots = ProjectRootManager.getInstance(this).contentRoots
if (contentRoots.isEmpty()) {
// this should cover for the case when no content roots are configured, e.g. in rider
Expand All @@ -440,3 +450,8 @@ fun Project.getContentRootVirtualFiles(): Set<VirtualFile> {
.filter { it.exists() && it.isDirectory }
.sortedBy { it.path }.toSet()
}

fun VirtualFile.isInContent(project: Project): Boolean {
val vf = this
return ReadAction.compute<Boolean, RuntimeException> { ProjectFileIndex.getInstance(project).isInContent(vf) }
}
16 changes: 0 additions & 16 deletions src/main/kotlin/io/snyk/plugin/analytics/AnalyticsScanListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,6 @@ class AnalyticsScanListener(val project: Project) {
start = System.currentTimeMillis()
}

override fun scanningIacFinished(iacResult: IacResult) {
val scanDoneEvent = getScanDoneEvent(
System.currentTimeMillis() - start,
"Snyk IaC",
iacResult.criticalSeveritiesCount(),
iacResult.highSeveritiesCount(),
iacResult.mediumSeveritiesCount(),
iacResult.lowSeveritiesCount()
)
LanguageServerWrapper.getInstance().sendReportAnalyticsCommand(scanDoneEvent)
}

override fun scanningContainerFinished(containerResult: ContainerResult) {
val scanDoneEvent = getScanDoneEvent(
System.currentTimeMillis() - start,
Expand All @@ -68,10 +56,6 @@ class AnalyticsScanListener(val project: Project) {
LanguageServerWrapper.getInstance().sendReportAnalyticsCommand(scanDoneEvent)
}

override fun scanningIacError(snykError: SnykError) {
// do nothing
}

override fun scanningContainerError(snykError: SnykError) {
// do nothing
}
Expand Down
5 changes: 0 additions & 5 deletions src/main/kotlin/io/snyk/plugin/events/SnykScanListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package io.snyk.plugin.events
import com.intellij.util.messages.Topic
import snyk.common.SnykError
import snyk.container.ContainerResult
import snyk.iac.IacResult

interface SnykScanListener {
companion object {
Expand All @@ -13,10 +12,6 @@ interface SnykScanListener {

fun scanningStarted()

fun scanningIacFinished(iacResult: IacResult)

fun scanningIacError(snykError: SnykError)

fun scanningContainerFinished(containerResult: ContainerResult)

fun scanningContainerError(snykError: SnykError)
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/io/snyk/plugin/events/SnykScanListenerLS.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ interface SnykScanListenerLS {

fun scanningOssFinished()

fun scanningIacFinished()

fun scanningError(snykScan: SnykScanParams)

fun onPublishDiagnostics(product: String, snykFile: SnykFile, issueList: List<ScanIssue>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,5 @@ interface SnykTaskQueueListener {
Topic.create("Snyk Task Queue", SnykTaskQueueListener::class.java)
}

fun stopped(
wasOssRunning: Boolean = false,
wasSnykCodeRunning: Boolean = false,
wasIacRunning: Boolean = false,
wasContainerRunning: Boolean = false
)
fun stopped()
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import java.util.UUID
storages = [Storage("snyk.settings.xml", roamingType = RoamingType.DISABLED)],
)
class SnykApplicationSettingsStateService : PersistentStateComponent<SnykApplicationSettingsStateService> {
val requiredLsProtocolVersion = 14
val requiredLsProtocolVersion = 15

var useTokenAuthentication = false
var currentLSProtocolVersion: Int? = 0
Expand All @@ -35,7 +35,7 @@ class SnykApplicationSettingsStateService : PersistentStateComponent<SnykApplica
var cliBaseDownloadURL: String = "https://downloads.snyk.io"
var cliPath: String = getPluginPath() + separator + Platform.current().snykWrapperFileName
var cliReleaseChannel = "stable"
var netNewIssues: String = "All issues"
var displayAllIssues: String = "All issues"
var manageBinariesAutomatically: Boolean = true
var fileListenerEnabled: Boolean = true
// TODO migrate to https://plugins.jetbrains.com/docs/intellij/persisting-sensitive-data.html?from=jetbrains.org
Expand Down Expand Up @@ -102,7 +102,7 @@ class SnykApplicationSettingsStateService : PersistentStateComponent<SnykApplica
}

fun isDeltaFindingsEnabled(): Boolean =
(netNewIssues == "Net new issues")
(displayAllIssues == "Net new issues")

fun getAdditionalParameters(project: Project? = null): String? =
if (isProjectSettingsAvailable(project)) {
Expand Down Expand Up @@ -178,7 +178,7 @@ class SnykApplicationSettingsStateService : PersistentStateComponent<SnykApplica
}

fun setDeltaEnabled() {
netNewIssues = "Net new issues"
displayAllIssues = "Net new issues"
}
}

Expand Down
Loading

0 comments on commit 14e0a29

Please sign in to comment.