3
3
4
4
package software.aws.toolkits.jetbrains.services.codewhisperer.codescan
5
5
6
- import com.intellij.analysis.problemsView.toolWindow.ProblemsView
7
6
import com.intellij.codeHighlighting.HighlightDisplayLevel
8
7
import com.intellij.codeInspection.util.InspectionMessage
9
8
import com.intellij.icons.AllIcons
10
9
import com.intellij.lang.Commenter
11
10
import com.intellij.lang.Language
12
11
import com.intellij.lang.LanguageCommenters
12
+ import com.intellij.openapi.Disposable
13
13
import com.intellij.openapi.actionSystem.ActionManager
14
14
import com.intellij.openapi.actionSystem.AnActionEvent
15
15
import com.intellij.openapi.actionSystem.CommonDataKeys
@@ -36,8 +36,10 @@ import com.intellij.openapi.util.Disposer
36
36
import com.intellij.openapi.util.TextRange
37
37
import com.intellij.openapi.vfs.VirtualFile
38
38
import com.intellij.openapi.vfs.isFile
39
+ import com.intellij.openapi.wm.ToolWindow
39
40
import com.intellij.psi.PsiDocumentManager
40
41
import com.intellij.refactoring.suggested.range
42
+ import com.intellij.ui.content.Content
41
43
import com.intellij.ui.content.ContentManagerEvent
42
44
import com.intellij.ui.content.ContentManagerListener
43
45
import com.intellij.ui.treeStructure.Tree
@@ -60,6 +62,7 @@ import software.aws.toolkits.core.utils.error
60
62
import software.aws.toolkits.core.utils.getLogger
61
63
import software.aws.toolkits.core.utils.info
62
64
import software.aws.toolkits.core.utils.warn
65
+ import software.aws.toolkits.jetbrains.ProblemsViewMutator
63
66
import software.aws.toolkits.jetbrains.core.coroutines.EDT
64
67
import software.aws.toolkits.jetbrains.core.coroutines.getCoroutineUiContext
65
68
import software.aws.toolkits.jetbrains.core.coroutines.projectCoroutineScope
@@ -107,26 +110,10 @@ import kotlin.coroutines.CoroutineContext
107
110
108
111
private val LOG = getLogger<CodeWhispererCodeScanManager >()
109
112
110
- class CodeWhispererCodeScanManager (val project : Project ) {
111
- private val defaultScope = projectCoroutineScope(project)
113
+ class CodeWhispererCodeScanManager (val project : Project , private val defaultScope : CoroutineScope ) : Disposable {
112
114
private val codeScanResultsPanel by lazy {
113
115
CodeWhispererCodeScanResultsView (project, defaultScope)
114
116
}
115
- private val codeScanIssuesContent by lazy {
116
- val contentManager = getProblemsWindow().contentManager
117
- contentManager.factory.createContent(
118
- codeScanResultsPanel,
119
- message(" codewhisperer.codescan.scan_display" ),
120
- false
121
- ).also {
122
- Disposer .register(contentManager, it)
123
- contentManager.addContentManagerListener(object : ContentManagerListener {
124
- override fun contentRemoved (event : ContentManagerEvent ) {
125
- if (event.content == it) reset()
126
- }
127
- })
128
- }
129
- }
130
117
131
118
private var autoScanIssues = emptyList<CodeWhispererCodeScanIssue >()
132
119
private var ondemandScanIssues = emptyList<CodeWhispererCodeScanIssue >()
@@ -507,12 +494,19 @@ class CodeWhispererCodeScanManager(val project: Project) {
507
494
private fun refreshUi () {
508
495
val codeScanTreeModel = CodeWhispererCodeScanTreeModel (codeScanTreeNodeRoot)
509
496
val totalIssuesCount = codeScanTreeModel.getTotalIssuesCount()
510
- if (totalIssuesCount > 0 ) {
511
- codeScanIssuesContent.displayName =
512
- message(" codewhisperer.codescan.scan_display_with_issues" , totalIssuesCount, INACTIVE_TEXT_COLOR )
497
+ val displayName = if (totalIssuesCount > 0 ) {
498
+ message(" codewhisperer.codescan.scan_display_with_issues" , totalIssuesCount, INACTIVE_TEXT_COLOR )
513
499
} else {
514
- codeScanIssuesContent.displayName = message(" codewhisperer.codescan.scan_display" )
500
+ message(" codewhisperer.codescan.scan_display" )
515
501
}
502
+
503
+ withToolWindow { window ->
504
+ window.contentManager.contents.filter { it.isCodeScanView() }
505
+ .forEach {
506
+ it.displayName = displayName
507
+ }
508
+ }
509
+
516
510
codeScanResultsPanel.refreshUIWithUpdatedModel(codeScanTreeModel)
517
511
}
518
512
@@ -650,26 +644,45 @@ class CodeWhispererCodeScanManager(val project: Project) {
650
644
* This method adds code content to the problems view if not already added.
651
645
*/
652
646
fun buildCodeScanUI () = runInEdt {
653
- val problemsWindow = getProblemsWindow()
654
- if (! problemsWindow.contentManager.contents.contains(codeScanIssuesContent)) {
655
- problemsWindow.contentManager.addContent(codeScanIssuesContent)
656
- codeScanIssuesContent.displayName = message(" codewhisperer.codescan.scan_display" )
647
+ withToolWindow { problemsWindow ->
648
+ val contentManager = problemsWindow.contentManager
649
+ if (! contentManager.contents.any { it.isCodeScanView() }) {
650
+ contentManager.addContent(
651
+ contentManager.factory.createContent(
652
+ codeScanResultsPanel,
653
+ message(" codewhisperer.codescan.scan_display" ),
654
+ false
655
+ ).also {
656
+ it.tabName = message(" codewhisperer.codescan.scan_display" )
657
+ Disposer .register(contentManager, it)
658
+ contentManager.addContentManagerListener(object : ContentManagerListener {
659
+ override fun contentRemoved (event : ContentManagerEvent ) {
660
+ if (event.content == it) reset()
661
+ }
662
+ })
663
+ }
664
+ )
665
+ }
657
666
}
658
667
}
659
668
660
669
/* *
661
670
* This method shows the code content panel in problems view
662
671
*/
663
672
fun showCodeScanUI () = runInEdt {
664
- val problemsWindow = getProblemsWindow()
665
- problemsWindow.contentManager.setSelectedContent(codeScanIssuesContent)
666
- problemsWindow.show()
673
+ withToolWindow { problemsWindow ->
674
+ problemsWindow.contentManager.contents.firstOrNull { it.isCodeScanView() }
675
+ ?.let { problemsWindow.contentManager.setSelectedContent(it) }
676
+ problemsWindow.show()
677
+ }
667
678
}
668
679
669
680
fun removeCodeScanUI () = runInEdt {
670
- val problemsWindow = getProblemsWindow()
671
- if (problemsWindow.contentManager.contents.contains(codeScanIssuesContent)) {
672
- problemsWindow.contentManager.removeContent(codeScanIssuesContent, false )
681
+ withToolWindow { problemsWindow ->
682
+ problemsWindow.contentManager.contents.filter { it.isCodeScanView() }
683
+ .forEach {
684
+ problemsWindow.contentManager.removeContent(it, true )
685
+ }
673
686
}
674
687
}
675
688
@@ -735,8 +748,13 @@ class CodeWhispererCodeScanManager(val project: Project) {
735
748
)
736
749
}
737
750
738
- private fun getProblemsWindow () = ProblemsView .getToolWindow(project)
739
- ? : error(message(" codewhisperer.codescan.problems_window_not_found" ))
751
+ private fun withToolWindow (runnable : (ToolWindow ) -> Unit ) {
752
+ ProblemsViewMutator .EP .forEachExtensionSafe { mutator ->
753
+ mutator.mutateProblemsView(project, runnable)
754
+ }
755
+ }
756
+
757
+ private fun Content.isCodeScanView () = component == codeScanResultsPanel
740
758
741
759
private fun reset () = runInEdt {
742
760
// clear the codeScanTreeNodeRoot
@@ -765,7 +783,7 @@ class CodeWhispererCodeScanManager(val project: Project) {
765
783
editorFactory.addEditorFactoryListener(fileListener, project)
766
784
editorFactory.eventMulticaster.addEditorMouseMotionListener(
767
785
editorMouseListener,
768
- codeScanIssuesContent
786
+ this
769
787
)
770
788
}
771
789
}
@@ -955,8 +973,12 @@ class CodeWhispererCodeScanManager(val project: Project) {
955
973
val codeScanTreeModel = CodeWhispererCodeScanTreeModel (codeScanTreeNodeRoot)
956
974
val totalIssuesCount = codeScanTreeModel.getTotalIssuesCount()
957
975
if (totalIssuesCount > 0 ) {
958
- codeScanIssuesContent.displayName =
959
- message(" codewhisperer.codescan.scan_display_with_issues" , totalIssuesCount, INACTIVE_TEXT_COLOR )
976
+ withToolWindow { problemsWindow ->
977
+ problemsWindow.contentManager.contents.filter { it.isCodeScanView() }
978
+ .forEach {
979
+ it.displayName = message(" codewhisperer.codescan.scan_display_with_issues" , totalIssuesCount, INACTIVE_TEXT_COLOR )
980
+ }
981
+ }
960
982
}
961
983
codeScanResultsPanel.refreshUIWithUpdatedModel(codeScanTreeModel)
962
984
}
@@ -971,8 +993,13 @@ class CodeWhispererCodeScanManager(val project: Project) {
971
993
val codeScanTreeModel = CodeWhispererCodeScanTreeModel (root)
972
994
val totalIssuesCount = codeScanTreeModel.getTotalIssuesCount()
973
995
if (totalIssuesCount > 0 ) {
974
- codeScanIssuesContent.displayName =
975
- message(" codewhisperer.codescan.scan_display_with_issues" , totalIssuesCount, INACTIVE_TEXT_COLOR )
996
+ withToolWindow { window ->
997
+ window.contentManager.contents.filter { it.isCodeScanView() }
998
+ .forEach {
999
+ it.displayName =
1000
+ message(" codewhisperer.codescan.scan_display_with_issues" , totalIssuesCount, INACTIVE_TEXT_COLOR )
1001
+ }
1002
+ }
976
1003
}
977
1004
codeScanResultsPanel.updateAndDisplayScanResults(codeScanTreeModel, scannedFiles, scope)
978
1005
}
@@ -1004,6 +1031,9 @@ class CodeWhispererCodeScanManager(val project: Project) {
1004
1031
return isInsideWorkTree(projectDir)
1005
1032
}
1006
1033
1034
+ override fun dispose () {
1035
+ }
1036
+
1007
1037
companion object {
1008
1038
fun getInstance (project : Project ): CodeWhispererCodeScanManager = project.service()
1009
1039
}
0 commit comments