@@ -7,10 +7,12 @@ import com.intellij.icons.AllIcons
77import com.intellij.openapi.actionSystem.ActionGroup
88import com.intellij.openapi.actionSystem.ActionManager
99import com.intellij.openapi.actionSystem.ActionToolbar
10+ import com.intellij.openapi.application.runInEdt
11+ import com.intellij.openapi.fileEditor.FileEditorManager
12+ import com.intellij.openapi.fileEditor.OpenFileDescriptor
1013import com.intellij.openapi.project.Project
1114import com.intellij.openapi.vfs.VirtualFile
1215import com.intellij.ui.AnimatedIcon
13- import com.intellij.ui.ClickListener
1416import com.intellij.ui.OnePixelSplitter
1517import com.intellij.ui.ScrollPaneFactory
1618import com.intellij.ui.border.CustomLineBorder
@@ -19,7 +21,8 @@ import com.intellij.ui.treeStructure.Tree
1921import com.intellij.util.ui.JBUI
2022import icons.AwsIcons
2123import kotlinx.coroutines.CoroutineScope
22- import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.listeners.CodeWhispererCodeScanTreeMouseListener
24+ import software.aws.toolkits.core.utils.error
25+ import software.aws.toolkits.core.utils.getLogger
2326import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.utils.IssueGroupingStrategy
2427import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.utils.IssueSeverity
2528import software.aws.toolkits.jetbrains.services.codewhisperer.layout.CodeWhispererLayoutConfig
@@ -31,7 +34,6 @@ import java.awt.BorderLayout
3134import java.awt.Component
3235import java.awt.GridBagConstraints
3336import java.awt.GridBagLayout
34- import java.awt.event.MouseEvent
3537import java.time.Instant
3638import java.time.format.DateTimeFormatter
3739import javax.swing.BorderFactory
@@ -52,15 +54,18 @@ internal class CodeWhispererCodeScanResultsView(private val project: Project, pr
5254
5355 private val codeScanTree: Tree = Tree ().apply {
5456 isRootVisible = false
55- CodeWhispererCodeScanTreeMouseListener (project).installOn(this )
56- object : ClickListener () {
57- override fun onClick (event : MouseEvent , clickCount : Int ): Boolean {
58- val issueNode = (event.source as Tree ).selectionPath?.lastPathComponent as ? DefaultMutableTreeNode
59- val issue = issueNode?.userObject as ? CodeWhispererCodeScanIssue ? : return false
60- showIssueDetails(issue, defaultScope)
61- return true
57+
58+ addTreeSelectionListener { e ->
59+ val issueNode = e.path.lastPathComponent as ? DefaultMutableTreeNode
60+ val issue = issueNode?.userObject as ? CodeWhispererCodeScanIssue ? : return @addTreeSelectionListener
61+
62+ showIssueDetails(issue, defaultScope)
63+
64+ synchronized(issueNode) {
65+ if (issueNode.userObject !is CodeWhispererCodeScanIssue ) return @addTreeSelectionListener
66+ navigateToIssue(issueNode.userObject as CodeWhispererCodeScanIssue )
6267 }
63- }.installOn( this )
68+ }
6469 cellRenderer = ColoredTreeCellRenderer ()
6570 }
6671
@@ -390,8 +395,30 @@ internal class CodeWhispererCodeScanResultsView(private val project: Project, pr
390395 }
391396 }
392397
398+ private fun navigateToIssue (codeScanIssue : CodeWhispererCodeScanIssue ) {
399+ val textRange = codeScanIssue.textRange ? : return
400+ val startOffset = textRange.startOffset
401+
402+ if (codeScanIssue.isInvalid) return
403+
404+ runInEdt {
405+ val editor = FileEditorManager .getInstance(project).openTextEditor(
406+ OpenFileDescriptor (project, codeScanIssue.file, startOffset),
407+ false
408+ )
409+ if (editor == null ) {
410+ LOG .error { " Cannot fetch editor for the file ${codeScanIssue.file.path} " }
411+ return @runInEdt
412+ }
413+ if (codeScanIssue.rangeHighlighter == null ) {
414+ codeScanIssue.rangeHighlighter = codeScanIssue.addRangeHighlighter(editor.markupModel)
415+ }
416+ }
417+ }
418+
393419 private companion object {
394420 const val ACTION_PLACE = " CodeScanResultsPanel"
395421 const val CODE_SCAN_SPLITTER_PROPORTION_KEY = " CODE_SCAN_SPLITTER_PROPORTION"
422+ private val LOG = getLogger<CodeWhispererCodeScanResultsView >()
396423 }
397424}
0 commit comments