[coverage] IDEA-347893 Always show the tool window in View/Tool windows and in Find Actions

GitOrigin-RevId: c8c69a9782b829b1ae5800cbc4a98ca0ce5be7ff
This commit is contained in:
Maksim Zuev
2024-02-29 14:44:42 +01:00
committed by intellij-monorepo-bot
parent 3706930931
commit b4580eaec2
6 changed files with 73 additions and 33 deletions

View File

@@ -20,6 +20,13 @@
<selectInTarget implementation="com.intellij.coverage.view.SelectInCoverageView"/>
<statistics.counterUsagesCollector implementationClass="com.intellij.coverage.CoverageLogger"/>
<toolWindow id="Coverage"
anchor="right"
factoryClass="com.intellij.coverage.view.CoverageToolWindowFactory"
icon="AllIcons.Toolwindows.ToolWindowCoverage"
secondary="true"
canCloseContents="true"
doNotActivateOnStart="true" />
</extensions>
<applicationListeners>
<listener class="com.intellij.coverage.CoverageDataManagerImpl$CoverageProjectManagerListener" topic="com.intellij.openapi.project.ProjectCloseListener"/>

View File

@@ -0,0 +1,40 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.coverage.view
import com.intellij.coverage.CoverageBundle
import com.intellij.coverage.actions.ExternalReportImportManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ToolWindowFactory
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.openapi.wm.ex.ToolWindowEx
import com.intellij.openapi.wm.impl.ToolWindowManagerImpl
import com.intellij.ui.SimpleTextAttributes
import com.intellij.ui.content.ContentManagerEvent
import com.intellij.ui.content.ContentManagerListener
class CoverageToolWindowFactory : ToolWindowFactory {
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
val manager = toolWindow.contentManager
manager.addContentManagerListener(object : ContentManagerListener {
override fun contentRemoved(event: ContentManagerEvent) {
if (manager.isEmpty) {
val toolWindowManager = ToolWindowManager.getInstance(project) as? ToolWindowManagerImpl ?: return
toolWindowManager.hideToolWindow(toolWindow.getId(), removeFromStripe = false)
}
}
})
val toolWindowEx = toolWindow as? ToolWindowEx ?: return
toolWindowEx.emptyText
?.appendLine(CoverageBundle.message("coverage.import.report.toolwindow.empty.text"), SimpleTextAttributes.LINK_PLAIN_ATTRIBUTES) {
ExternalReportImportManager.getInstance(toolWindow.project).chooseAndOpenSuites()
}
}
override fun init(toolWindow: ToolWindow) {
toolWindow.apply {
stripeTitle = CoverageBundle.message("coverage.view.title")
helpId = CoverageView.HELP_ID
}
}
}

View File

@@ -1,24 +1,19 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.coverage.view
import com.intellij.coverage.CoverageBundle
import com.intellij.coverage.CoverageOptionsProvider
import com.intellij.coverage.CoverageSuitesBundle
import com.intellij.coverage.actions.ExternalReportImportManager
import com.intellij.coverage.view.CoverageViewManager.StateBean
import com.intellij.icons.AllIcons
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.components.*
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.NlsSafe
import com.intellij.openapi.wm.ToolWindowAnchor
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.ui.SimpleTextAttributes
import com.intellij.ui.content.ContentManager
import com.intellij.util.concurrency.annotations.RequiresEdt
import com.intellij.util.containers.DisposableWrapperList
import com.intellij.util.ui.ComponentWithEmptyText
import org.jetbrains.annotations.NonNls
@State(name = "CoverageViewManager", storages = [Storage(StoragePathMacros.PRODUCT_WORKSPACE_FILE)])
@@ -31,23 +26,6 @@ class CoverageViewManager(private val myProject: Project) : PersistentStateCompo
@Volatile
private var myContentManager: ContentManager? = null
@RequiresEdt
private fun initializeToolWindow(): ContentManager? {
if (myProject.isDisposed || !myProject.isOpen) return null
val toolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(TOOLWINDOW_ID) {
sideTool = true
icon = AllIcons.Toolwindows.ToolWindowCoverage
anchor = ToolWindowAnchor.RIGHT
stripeTitle = CoverageBundle.messagePointer("coverage.view.title")
}
toolWindow.helpId = CoverageView.HELP_ID
(toolWindow.component as? ComponentWithEmptyText)?.emptyText
?.appendLine(CoverageBundle.message("coverage.import.report.toolwindow.empty.text"), SimpleTextAttributes.LINK_PLAIN_ATTRIBUTES) {
ExternalReportImportManager.getInstance(myProject).chooseAndOpenSuites()
}
return toolWindow.contentManager
}
override fun getState(): StateBean {
if (!myViews.isEmpty()) {
val view = myViews.values.iterator().next()
@@ -68,8 +46,7 @@ class CoverageViewManager(private val myProject: Project) : PersistentStateCompo
val openedSuite: CoverageSuitesBundle?
get() {
val manager = myContentManager ?: return null
val selectedContent = manager.selectedContent
if (selectedContent == null) return null
val selectedContent = manager.selectedContent ?: return null
return myViews.firstNotNullOfOrNull { (suite, view) -> suite.takeIf { selectedContent === manager.getContent(view) } }
}
@@ -77,8 +54,7 @@ class CoverageViewManager(private val myProject: Project) : PersistentStateCompo
fun activateToolwindow(view: CoverageView) {
val manager = myContentManager ?: return
manager.setSelectedContent(manager.getContent(view))
val toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(TOOLWINDOW_ID)
?: error("Coverage toolwindow is not registered")
val toolWindow = getToolWindow() ?: error("Coverage toolwindow is not registered")
toolWindow.activate(null, false)
}
@@ -136,15 +112,13 @@ class CoverageViewManager(private val myProject: Project) : PersistentStateCompo
createView(suitesBundle, activate)
}
/**
* Call to this method initializes the coverage tool window.
*/
@RequiresEdt
private fun getContentManager(): ContentManager? {
myContentManager?.also { return it }
return initializeToolWindow()?.also { myContentManager = it }
return getToolWindow()?.contentManager?.also { myContentManager = it }
}
private fun getToolWindow(): ToolWindow? = ToolWindowManager.getInstance(myProject).getToolWindow(TOOLWINDOW_ID)
class StateBean {
private var myFlattenPackages = false

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.coverage
import com.intellij.coverage.view.registerCoverageToolWindow
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.ex.ActionUtil
@@ -124,6 +125,7 @@ class CoverageSuitesTest : CoverageIntegrationBaseTest() {
@Test
fun `test opening several suites`(): Unit = runBlocking {
registerCoverageToolWindow(myProject)
assertNoSuites()
val ijSuite = loadIJSuite()
val xmlSuite = loadXMLSuite()

View File

@@ -12,6 +12,7 @@ import com.intellij.util.ui.tree.TreeUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -19,6 +20,10 @@ import javax.swing.JTree
@RunWith(JUnit4::class)
class CoverageTreeTest : CoverageIntegrationBaseTest() {
@Before
fun init() {
registerCoverageToolWindow(myProject)
}
@Test
fun `test ij coverage tree contains elements`() = testCoverageSuiteTree(loadFullSuite(), false, """

View File

@@ -3,9 +3,12 @@ package com.intellij.coverage.view
import com.intellij.coverage.CoverageIntegrationBaseTest
import com.intellij.coverage.CoverageSuitesBundle
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.toolWindow.ToolWindowHeadlessManagerImpl
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -14,6 +17,10 @@ private const val TIMEOUT_MS = 20_000L
@RunWith(JUnit4::class)
class CoverageViewTest : CoverageIntegrationBaseTest() {
@Before
fun init() {
registerCoverageToolWindow(myProject)
}
@Test(timeout = TIMEOUT_MS)
fun `test coverage toolwindow exists`() = runBlocking {
@@ -68,5 +75,10 @@ class CoverageViewTest : CoverageIntegrationBaseTest() {
private fun findCoverageView(bundle: CoverageSuitesBundle): CoverageView? = CoverageViewManager.getInstance(myProject).getView(bundle)
private fun getCoverageToolWindow() = ToolWindowManager.getInstance(myProject).getToolWindow(CoverageViewManager.TOOLWINDOW_ID)
private fun assertToolWindowExists() = Assert.assertNotNull(getCoverageToolWindow())
private fun assertToolWindowDoesNotExist() = Assert.assertNull(getCoverageToolWindow())
private fun assertToolWindowDoesNotExist() = getCoverageToolWindow()?.isActive == false
}
internal fun registerCoverageToolWindow(project: Project) {
val toolWindowManager = ToolWindowManager.getInstance(project) as ToolWindowHeadlessManagerImpl
toolWindowManager.doRegisterToolWindow(CoverageViewManager.TOOLWINDOW_ID)
}