diff --git a/build.gradle.kts b/build.gradle.kts index 37e1c8d12..79c7ae9c1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ repositories { dependencies { implementation(platform("com.squareup.okhttp3:okhttp-bom:4.12.0")) implementation(platform("com.squareup.retrofit2:retrofit-bom:2.11.0")) - implementation("org.eclipse.lsp4j:org.eclipse.lsp4j:0.22.0") + implementation("org.eclipse.lsp4j:org.eclipse.lsp4j:0.23.1") implementation("org.commonmark:commonmark:0.21.0") implementation("com.google.code.gson:gson:2.10.1") diff --git a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanel.kt b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanel.kt index dc37fba2b..de224d261 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanel.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanel.kt @@ -65,6 +65,7 @@ import io.snyk.plugin.ui.toolwindow.panels.StatePanel import io.snyk.plugin.ui.toolwindow.panels.TreePanel import io.snyk.plugin.ui.wrapWithScrollPane import org.jetbrains.annotations.TestOnly +import org.jetbrains.concurrency.runAsync import snyk.common.ProductType import snyk.common.SnykError import snyk.common.lsp.LanguageServerWrapper @@ -79,6 +80,7 @@ import java.awt.BorderLayout import java.util.Objects.nonNull import javax.swing.JPanel import javax.swing.JScrollPane +import javax.swing.event.TreeSelectionEvent import javax.swing.tree.DefaultMutableTreeNode import javax.swing.tree.DefaultTreeModel import javax.swing.tree.TreePath @@ -93,7 +95,7 @@ class SnykToolWindowPanel( Disposable { private val descriptionPanel = SimpleToolWindowPanel(true, true).apply { name = "descriptionPanel" } private val logger = Logger.getInstance(this::class.java) - private val rootTreeNode = ChooseBranchNode(project = project) + private val rootTreeNode = ChooseBranchNode(project = project) private val rootOssTreeNode = RootOssTreeNode(project) private val rootSecurityIssuesTreeNode = RootSecurityIssuesTreeNode(project) private val rootQualityIssuesTreeNode = RootQualityIssuesTreeNode(project) @@ -129,10 +131,10 @@ class SnykToolWindowPanel( } - init { val folderConfig = service().getFolderConfig(project.basePath.toString()) - val rootNodeText = folderConfig?.let { getRootNodeText(it.folderPath, it.baseBranch) } ?: "Choose branch on ${project.basePath}" + val rootNodeText = folderConfig?.let { getRootNodeText(it.folderPath, it.baseBranch) } + ?: "Choose branch on ${project.basePath}" rootTreeNode.info = rootNodeText vulnerabilitiesTree.cellRenderer = SnykTreeCellRenderer() @@ -148,8 +150,10 @@ class SnykToolWindowPanel( createTreeAndDescriptionPanel() chooseMainPanelToDisplay() - vulnerabilitiesTree.selectionModel.addTreeSelectionListener { - updateDescriptionPanelBySelectedTreeNode() + vulnerabilitiesTree.selectionModel.addTreeSelectionListener { treeSelectionEvent -> + runAsync { + updateDescriptionPanelBySelectedTreeNode(treeSelectionEvent) + } } val scanListenerLS = @@ -316,45 +320,74 @@ class SnykToolWindowPanel( ) } - private fun updateDescriptionPanelBySelectedTreeNode() { + private fun updateDescriptionPanelBySelectedTreeNode(treeSelectionEvent: TreeSelectionEvent) { val capturedSmartReloadMode = smartReloadMode val capturedNavigateToSourceEnabled = triggerSelectionListeners - ApplicationManager.getApplication().invokeLater { - descriptionPanel.removeAll() - val selectionPath = vulnerabilitiesTree.selectionPath - if (nonNull(selectionPath)) { - val lastPathComponent = selectionPath!!.lastPathComponent + val selectionPath = treeSelectionEvent.path + if (nonNull(selectionPath) && treeSelectionEvent.isAddedPath) { + val lastPathComponent = selectionPath.lastPathComponent - if (lastPathComponent is ChooseBranchNode && capturedNavigateToSourceEnabled && !capturedSmartReloadMode) { + if (lastPathComponent is ChooseBranchNode && capturedNavigateToSourceEnabled && !capturedSmartReloadMode) { + invokeLater { BranchChooserComboBoxDialog(project).show() } + } - if (!capturedSmartReloadMode && - capturedNavigateToSourceEnabled && - lastPathComponent is NavigatableToSourceTreeNode - ) { - lastPathComponent.navigateToSource() - } - when (val selectedNode: DefaultMutableTreeNode = lastPathComponent as DefaultMutableTreeNode) { - is DescriptionHolderTreeNode -> { + if (!capturedSmartReloadMode && + capturedNavigateToSourceEnabled && + lastPathComponent is NavigatableToSourceTreeNode + ) { + lastPathComponent.navigateToSource() + } + when (val selectedNode: DefaultMutableTreeNode = lastPathComponent as DefaultMutableTreeNode) { + is DescriptionHolderTreeNode -> { + if (selectedNode is SuggestionTreeNode) { + val cache = getSnykCachedResults(project) ?: return + val issue = selectedNode.issue + val productIssues = when (issue.filterableIssueType) { + ScanIssue.CODE_SECURITY, ScanIssue.CODE_QUALITY -> cache.currentSnykCodeResultsLS + ScanIssue.OPEN_SOURCE -> cache.currentOSSResultsLS + ScanIssue.INFRASTRUCTURE_AS_CODE -> cache.currentIacResultsLS + ScanIssue.CONTAINER -> cache.currentContainerResultsLS + else -> { + emptyMap() + } + } + productIssues.values.flatten().filter { issue.id == it.id }.forEach { _ -> + val newDescriptionPanel = selectedNode.getDescriptionPanel() + descriptionPanel.removeAll() + descriptionPanel.add( + newDescriptionPanel, + BorderLayout.CENTER, + ) + } + } else { + descriptionPanel.removeAll() descriptionPanel.add( selectedNode.getDescriptionPanel(), BorderLayout.CENTER, ) } - is ErrorHolderTreeNode -> { - selectedNode.getSnykError()?.let { - displaySnykError(it) - } ?: displayEmptyDescription() - } + } - else -> displayEmptyDescription() + is ErrorHolderTreeNode -> { + descriptionPanel.removeAll() + selectedNode.getSnykError()?.let { + displaySnykError(it) + } ?: displayEmptyDescription() + } + + else -> { + descriptionPanel.removeAll() + displayEmptyDescription() } - } else { - displayEmptyDescription() } + } else { + displayEmptyDescription() + } + invokeLater { descriptionPanel.revalidate() descriptionPanel.repaint() } @@ -842,9 +875,6 @@ class SnykToolWindowPanel( smartReloadMode = true try { selectedNode?.let { TreeUtil.selectNode(vulnerabilitiesTree, it) } - // for some reason TreeSelectionListener is not initiated here on node selection - // also we need to update Description panel in case if no selection was made before - updateDescriptionPanelBySelectedTreeNode() } finally { smartReloadMode = false } diff --git a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowSnykScanListenerLS.kt b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowSnykScanListenerLS.kt index 5e4cb8aed..abd2d375c 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowSnykScanListenerLS.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowSnykScanListenerLS.kt @@ -13,6 +13,7 @@ import io.snyk.plugin.events.SnykScanListenerLS import io.snyk.plugin.getSnykCachedResults import io.snyk.plugin.pluginSettings import io.snyk.plugin.refreshAnnotationsForOpenFiles +import io.snyk.plugin.ui.expandTreeNodeRecursively import io.snyk.plugin.ui.toolwindow.SnykToolWindowPanel.Companion.CODE_QUALITY_ROOT_TEXT import io.snyk.plugin.ui.toolwindow.SnykToolWindowPanel.Companion.CODE_SECURITY_ROOT_TEXT import io.snyk.plugin.ui.toolwindow.SnykToolWindowPanel.Companion.IAC_ROOT_TEXT @@ -422,12 +423,14 @@ class SnykToolWindowSnykScanListenerLS( .forEach { issue -> fileTreeNode.add( SuggestionTreeNode( + project, issue, navigateToSource(entry.key.virtualFile, issue.textRange ?: TextRange(0, 0)), ), ) } } + expandTreeNodeRecursively(snykToolWindowPanel.vulnerabilitiesTree, rootNode) } private fun buildSeveritiesPostfixForFileNode(results: Map>): String { diff --git a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/nodes/leaf/SuggestionTreeNode.kt b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/nodes/leaf/SuggestionTreeNode.kt index d6c4e60a6..85a83550b 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/nodes/leaf/SuggestionTreeNode.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/nodes/leaf/SuggestionTreeNode.kt @@ -1,29 +1,21 @@ package io.snyk.plugin.ui.toolwindow.nodes.leaf -import io.snyk.plugin.SnykFile +import com.intellij.openapi.project.Project import io.snyk.plugin.ui.toolwindow.nodes.DescriptionHolderTreeNode import io.snyk.plugin.ui.toolwindow.nodes.NavigatableToSourceTreeNode -import io.snyk.plugin.ui.toolwindow.nodes.secondlevel.SnykFileTreeNode import io.snyk.plugin.ui.toolwindow.panels.IssueDescriptionPanelBase import io.snyk.plugin.ui.toolwindow.panels.SuggestionDescriptionPanelFromLS -import snyk.common.ProductType import snyk.common.lsp.ScanIssue import javax.swing.tree.DefaultMutableTreeNode class SuggestionTreeNode( - private val issue: ScanIssue, + val project: Project, + val issue: ScanIssue, override val navigateToSource: () -> Unit ) : DefaultMutableTreeNode(issue), NavigatableToSourceTreeNode, DescriptionHolderTreeNode { @Suppress("UNCHECKED_CAST") override fun getDescriptionPanel(): IssueDescriptionPanelBase { - val snykFileTreeNode = this.parent as? SnykFileTreeNode - ?: throw IllegalArgumentException(this.toString()) - - @Suppress("UNCHECKED_CAST") - val entry = - (snykFileTreeNode.userObject as Pair>, ProductType>).first - val snykFile = entry.key - return SuggestionDescriptionPanelFromLS(snykFile, issue) + return SuggestionDescriptionPanelFromLS(project, issue) } } diff --git a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/panels/JCEFDescriptionPanel.kt b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/panels/JCEFDescriptionPanel.kt index bc8b02a34..30c58e465 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/panels/JCEFDescriptionPanel.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/panels/JCEFDescriptionPanel.kt @@ -2,11 +2,11 @@ package io.snyk.plugin.ui.toolwindow.panels import com.intellij.openapi.editor.colors.EditorColors import com.intellij.openapi.editor.colors.EditorColorsManager +import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.uiDesigner.core.GridLayoutManager import com.intellij.util.ui.JBUI import com.intellij.util.ui.UIUtil -import io.snyk.plugin.SnykFile import io.snyk.plugin.toVirtualFile import io.snyk.plugin.ui.DescriptionHeaderPanel import io.snyk.plugin.ui.SnykBalloonNotificationHelper @@ -31,13 +31,12 @@ import javax.swing.JPanel import kotlin.collections.set class SuggestionDescriptionPanelFromLS( - snykFile: SnykFile, + val project: Project, private val issue: ScanIssue, ) : IssueDescriptionPanelBase( title = issue.title(), severity = issue.getSeverityAsEnum(), ) { - val project = snykFile.project private val unexpectedErrorMessage = "Snyk encountered an issue while rendering the vulnerability description. Please try again, or contact support if the problem persists. We apologize for any inconvenience caused." @@ -57,7 +56,7 @@ class SuggestionDescriptionPanelFromLS( virtualFiles[dataFlow.filePath] = dataFlow.filePath.toVirtualFile() } - val openFileLoadHandlerGenerator = OpenFileLoadHandlerGenerator(snykFile.project, virtualFiles) + val openFileLoadHandlerGenerator = OpenFileLoadHandlerGenerator(project, virtualFiles) loadHandlerGenerators += { openFileLoadHandlerGenerator.generate(it) } @@ -67,7 +66,7 @@ class SuggestionDescriptionPanelFromLS( generateAIFixHandler.generateAIFixCommand(it) } - val applyFixHandler = ApplyFixHandler(snykFile.project) + val applyFixHandler = ApplyFixHandler(project) loadHandlerGenerators += { applyFixHandler.generateApplyFixCommand(it) } @@ -193,6 +192,11 @@ class SuggestionDescriptionPanelFromLS( editorBackground ) + html = html.replace( + "var(--editor-color)", + editorBackground + ) + return html } diff --git a/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt b/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt index 0e8464c18..32dfc850a 100644 --- a/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt +++ b/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt @@ -20,9 +20,6 @@ import io.snyk.plugin.pluginSettings import io.snyk.plugin.runInBackground import io.snyk.plugin.toLanguageServerURL import io.snyk.plugin.ui.toolwindow.SnykPluginDisposable -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import org.eclipse.lsp4j.ClientCapabilities import org.eclipse.lsp4j.ClientInfo import org.eclipse.lsp4j.CodeActionCapabilities @@ -120,7 +117,6 @@ class LanguageServerWrapper( var isInitialized: Boolean = false - @OptIn(DelicateCoroutinesApi::class) private fun initialize() { if (disposed) return if (lsPath.toNioPathOrNull()?.exists() == false) { @@ -143,7 +139,8 @@ class LanguageServerWrapper( EnvironmentHelper.updateEnvironment(processBuilder.environment(), pluginSettings().token ?: "") process = processBuilder.start() - GlobalScope.launch { + + runAsync { if (!disposed) { try { process.errorStream.bufferedReader().forEachLine { logger.debug(it) } @@ -160,14 +157,16 @@ class LanguageServerWrapper( runAsync { listenerFuture.get() + logger.info("Snyk Language Server was terminated, listener has ended.") isInitialized = false } - if (!listenerFuture.isDone) { + if (!(listenerFuture.isDone || listenerFuture.isCancelled)) { sendInitializeMessage() isInitialized = true // listen for downloads / restarts LanguageServerRestartListener.getInstance() + refreshFeatureFlags() } else { logger.warn("Language Server initialization did not succeed") } @@ -525,19 +524,21 @@ class LanguageServerWrapper( } } - fun generateIssueDescription(issueID: String): String? { + fun generateIssueDescription(issue: ScanIssue): String? { if (!ensureLanguageServerInitialized()) return null - try { - val generateIssueCommand = ExecuteCommandParams(SNYK_GENERATE_ISSUE_DESCRIPTION, listOf(issueID)) - val result = - languageServer.workspaceService - .executeCommand(generateIssueCommand) - .get(2, TimeUnit.SECONDS) - .toString() - return result + val key = issue.additionalData.key + if (key.isBlank()) throw RuntimeException("Issue ID is required") + val generateIssueCommand = ExecuteCommandParams(SNYK_GENERATE_ISSUE_DESCRIPTION, listOf(key)) + return try { + logger.info("########### calling generateIssueDescription") + executeCommand(generateIssueCommand, 10000).toString() } catch (e: TimeoutException) { - logger.warn("could not generate html description", e) - return null + val exceptionMessage = "generate issue description failed" + logger.warn(exceptionMessage, e) + null + } catch (e: Exception) { + logger.error("generate issue description failed", e) + null } } @@ -545,7 +546,7 @@ class LanguageServerWrapper( if (!ensureLanguageServerInitialized()) return val cmd = ExecuteCommandParams(COMMAND_LOGOUT, emptyList()) try { - languageServer.workspaceService.executeCommand(cmd).get(5, TimeUnit.SECONDS) + executeCommand(cmd) } catch (e: TimeoutException) { logger.warn("could not logout", e) } @@ -567,7 +568,7 @@ class LanguageServerWrapper( val param = ExecuteCommandParams() param.command = COMMAND_CODE_FIX_DIFFS param.arguments = listOf(folderURI, fileURI, issueID) - val result = languageServer.workspaceService.executeCommand(param).get(120, TimeUnit.SECONDS) as List<*> + val result = executeCommand(param, 120000) as List<*> val diffList: MutableList = mutableListOf() result.forEach { @@ -595,7 +596,7 @@ class LanguageServerWrapper( val param = ExecuteCommandParams() param.command = COMMAND_CODE_SUBMIT_FIX_FEEDBACK param.arguments = listOf(fixId, feedback) - languageServer.workspaceService.executeCommand(param) + executeCommand(param) } catch (err: Exception) { logger.warn("Error in submitAutofixFeedbackCommand", err) } @@ -631,8 +632,7 @@ class LanguageServerWrapper( if (!ensureLanguageServerInitialized()) return null try { val executeCommandParams = ExecuteCommandParams(COMMAND_GET_SETTINGS_SAST_ENABLED, emptyList()) - val response = - languageServer.workspaceService.executeCommand(executeCommandParams).get(10, TimeUnit.SECONDS) + val response = executeCommand(executeCommandParams, 10000) if (response is Map<*, *>) { val localCodeEngineMap: Map = response["localCodeEngine"] as Map return SastSettings( diff --git a/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt b/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt index 93b758c82..cfcac6bf9 100644 --- a/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt +++ b/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt @@ -238,7 +238,6 @@ class SnykLanguageClient : when (snykScan.product) { "oss" -> scanPublisher.scanningOssFinished() "code" -> { - LanguageServerWrapper.getInstance().refreshFeatureFlags() scanPublisher.scanningSnykCodeFinished() } "iac" -> scanPublisher.scanningIacFinished() @@ -270,11 +269,12 @@ class SnykLanguageClient : @JsonNotification(value = "$/snyk.hasAuthenticated") fun hasAuthenticated(param: HasAuthenticatedParam) { if (disposed) return - if (pluginSettings().token == param.token) return + val oldToken = pluginSettings().token + if (oldToken == param.token) return pluginSettings().token = param.token ApplicationManager.getApplication().saveSettings() - if (pluginSettings().token?.isNotEmpty() == true && pluginSettings().scanOnSave) { + if (oldToken.isNullOrBlank() && !param.token.isNullOrBlank() && pluginSettings().scanOnSave) { val wrapper = LanguageServerWrapper.getInstance() ProjectManager.getInstance().openProjects.forEach { wrapper.sendScanCommand(it) diff --git a/src/main/kotlin/snyk/common/lsp/Types.kt b/src/main/kotlin/snyk/common/lsp/Types.kt index 626705b78..b5f951d0a 100644 --- a/src/main/kotlin/snyk/common/lsp/Types.kt +++ b/src/main/kotlin/snyk/common/lsp/Types.kt @@ -261,10 +261,11 @@ data class ScanIssue( } private fun getHtml(details: String?): String { - if (details.isNullOrEmpty()) { - return LanguageServerWrapper.getInstance().generateIssueDescription(this.id) ?: "" + return if (details.isNullOrEmpty() && this.id.isNotBlank()) { + LanguageServerWrapper.getInstance().generateIssueDescription(this) ?: "" + } else { + "" } - return details } fun annotationMessage(): String { diff --git a/src/main/resources/stylesheets/snyk_code_suggestion.scss b/src/main/resources/stylesheets/snyk_code_suggestion.scss index 979074892..6d2dda653 100644 --- a/src/main/resources/stylesheets/snyk_code_suggestion.scss +++ b/src/main/resources/stylesheets/snyk_code_suggestion.scss @@ -78,10 +78,6 @@ a, border-bottom: 3px solid #3474f0; } -.example-line { - background-color: var(--editor-color); -} - .example-line.added { background-color: var(--example-line-added-color); } diff --git a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelTest.kt b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelTest.kt index 90149c534..f4ceef6d1 100644 --- a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelTest.kt +++ b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelTest.kt @@ -9,7 +9,6 @@ import io.mockk.every import io.mockk.justRun import io.mockk.mockk import io.mockk.unmockkAll -import io.mockk.verify import io.snyk.plugin.pluginSettings import io.snyk.plugin.services.SnykApplicationSettingsStateService import io.snyk.plugin.services.SnykTaskQueueService diff --git a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SuggestionDescriptionPanelFromLSCodeTest.kt b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SuggestionDescriptionPanelFromLSCodeTest.kt index 512b0a9dd..10655d408 100644 --- a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SuggestionDescriptionPanelFromLSCodeTest.kt +++ b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SuggestionDescriptionPanelFromLSCodeTest.kt @@ -83,7 +83,7 @@ class SuggestionDescriptionPanelFromLSCodeTest : BasePlatformTestCase() { every { issue.details() } returns "HTML message" every { issue.canLoadSuggestionPanelFromHTML() } returns true - cut = SuggestionDescriptionPanelFromLS(snykFile, issue) + cut = SuggestionDescriptionPanelFromLS(project, issue) val actual = getJLabelByText(cut, "Test message") assertNull(actual) @@ -101,7 +101,7 @@ class SuggestionDescriptionPanelFromLSCodeTest : BasePlatformTestCase() { every { issue.details() } returns "HTML message" every { issue.canLoadSuggestionPanelFromHTML() } returns true - cut = SuggestionDescriptionPanelFromLS(snykFile, issue) + cut = SuggestionDescriptionPanelFromLS(project, issue) val actual = getJLabelByText(cut, "Test message") assertNull(actual) @@ -113,7 +113,7 @@ class SuggestionDescriptionPanelFromLSCodeTest : BasePlatformTestCase() { fun `test getStyledHTML should inject CSS into the HTML if allowed`() { every { issue.details() } returns "\${ideStyle}HTML message" every { issue.canLoadSuggestionPanelFromHTML() } returns true - cut = SuggestionDescriptionPanelFromLS(snykFile, issue) + cut = SuggestionDescriptionPanelFromLS(project, issue) val actual = cut.getCustomCssAndScript() assertFalse(actual.contains("\${ideStyle}")) diff --git a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SuggestionDescriptionPanelFromLSOSSTest.kt b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SuggestionDescriptionPanelFromLSOSSTest.kt index 619dacd68..25db01134 100644 --- a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SuggestionDescriptionPanelFromLSOSSTest.kt +++ b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SuggestionDescriptionPanelFromLSOSSTest.kt @@ -83,7 +83,7 @@ class SuggestionDescriptionPanelFromLSOSSTest : BasePlatformTestCase() { every { issue.details() } returns "HTML message" every { issue.canLoadSuggestionPanelFromHTML() } returns true - cut = SuggestionDescriptionPanelFromLS(snykFile, issue) + cut = SuggestionDescriptionPanelFromLS(project, issue) val actual = getJLabelByText(cut, "Test message") assertNull(actual) @@ -95,7 +95,7 @@ class SuggestionDescriptionPanelFromLSOSSTest : BasePlatformTestCase() { fun `test getStyledHTML should inject CSS into the HTML if allowed`() { every { issue.details() } returns "HTML message" every { issue.canLoadSuggestionPanelFromHTML() } returns true - cut = SuggestionDescriptionPanelFromLS(snykFile, issue) + cut = SuggestionDescriptionPanelFromLS(project, issue) val actual = cut.getCustomCssAndScript()