[coverage] IDEA-343368 Prevent coverage toolwindow from creating unless a report is opening

GitOrigin-RevId: 3c7195612255e744389ff14a21fab95ec144d214
This commit is contained in:
Maksim Zuev
2024-01-18 14:27:26 +01:00
committed by intellij-monorepo-bot
parent 6b4bc8b15c
commit 2abdd7ca16
6 changed files with 71 additions and 59 deletions

View File

@@ -124,8 +124,11 @@ public class CoverageDataManagerImpl extends CoverageDataManager implements Disp
@Override
public CoverageSuitesBundle getCurrentSuitesBundle() {
CoverageSuitesBundle openedSuite = CoverageViewManager.getInstance(myProject).getOpenedSuite();
if (openedSuite != null) return openedSuite;
CoverageViewManager manager = CoverageViewManager.getInstanceIfCreated(myProject);
if (manager != null) {
CoverageSuitesBundle openedSuite = manager.getOpenedSuite();
if (openedSuite != null) return openedSuite;
}
return myActiveBundles.values().stream().findFirst().orElse(null);
}

View File

@@ -26,7 +26,6 @@ public abstract class CoverageViewExtension {
protected final CoverageSuitesBundle mySuitesBundle;
protected final CoverageViewManager.StateBean myStateBean;
protected final CoverageDataManager myCoverageDataManager;
protected final CoverageViewManager myCoverageViewManager;
public CoverageViewExtension(@NotNull Project project, CoverageSuitesBundle suitesBundle, CoverageViewManager.StateBean stateBean) {
assert !project.isDefault() : "Should not run coverage for default project";
@@ -34,7 +33,6 @@ public abstract class CoverageViewExtension {
mySuitesBundle = suitesBundle;
myStateBean = stateBean;
myCoverageDataManager = CoverageDataManager.getInstance(myProject);
myCoverageViewManager = CoverageViewManager.getInstance(myProject);
}
@Nullable

View File

@@ -7,38 +7,38 @@ import com.intellij.coverage.CoverageSuitesBundle
import com.intellij.coverage.view.CoverageViewManager.StateBean
import com.intellij.icons.AllIcons
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.components.*
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.NlsSafe
import com.intellij.openapi.wm.ToolWindowAnchor
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.ui.AppUIUtil.invokeLaterIfProjectAlive
import com.intellij.ui.content.Content
import com.intellij.ui.content.ContentManager
import com.intellij.util.concurrency.annotations.RequiresEdt
import com.intellij.util.containers.DisposableWrapperList
import org.jetbrains.annotations.NonNls
@State(name = "CoverageViewManager", storages = [Storage(StoragePathMacros.PRODUCT_WORKSPACE_FILE)])
@Service(Service.Level.PROJECT)
class CoverageViewManager(private val myProject: Project) : PersistentStateComponent<StateBean?>, Disposable.Default {
private var myContentManager: ContentManager? = null
var stateBean = StateBean()
private set
private val myViews: MutableMap<CoverageSuitesBundle, CoverageView> = HashMap()
init {
invokeLaterIfProjectAlive(myProject) {
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
myContentManager = toolWindow.contentManager
@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
return toolWindow.contentManager
}
override fun getState(): StateBean {
@@ -60,41 +60,35 @@ class CoverageViewManager(private val myProject: Project) : PersistentStateCompo
val openedSuite: CoverageSuitesBundle?
get() {
val manager = myContentManager
if (manager == null) return null
val manager = myContentManager ?: return null
val selectedContent = manager.selectedContent
if (selectedContent == null) return null
for ((key, value) in myViews) {
val content = manager.getContent(value)
if (content === selectedContent) {
return key
}
}
return null
return myViews.firstNotNullOfOrNull { (suite, view) -> suite.takeIf { selectedContent === manager.getContent(view) } }
}
@RequiresEdt
fun activateToolwindow(view: CoverageView) {
myContentManager!!.setSelectedContent(myContentManager!!.getContent(view))
val manager = myContentManager ?: return
manager.setSelectedContent(manager.getContent(view))
val toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(TOOLWINDOW_ID)
LOG.assertTrue(toolWindow != null)
toolWindow!!.activate(null, false)
?: error("Coverage toolwindow is not registered")
toolWindow.activate(null, false)
}
@Synchronized
@RequiresEdt
fun createView(suitesBundle: CoverageSuitesBundle, activate: Boolean) {
var coverageView = myViews[suitesBundle]
val content: Content
if (coverageView == null) {
val manager = getContentManager() ?: return
val content = if (coverageView == null) {
coverageView = CoverageView(myProject, suitesBundle, stateBean)
myViews[suitesBundle] = coverageView
content = myContentManager!!.factory.createContent(coverageView, getDisplayName(suitesBundle), false)
myContentManager!!.addContent(content)
manager.factory.createContent(coverageView, getDisplayName(suitesBundle), false)
.also { manager.addContent(it) }
}
else {
content = myContentManager!!.getContent(coverageView)
manager.getContent(coverageView)
}
myContentManager!!.setSelectedContent(content)
manager.setSelectedContent(content)
if (CoverageOptionsProvider.getInstance(myProject).activateViewOnRun() && activate) {
activateToolwindow(coverageView)
}
@@ -104,10 +98,11 @@ class CoverageViewManager(private val myProject: Project) : PersistentStateCompo
val oldView = myViews.remove(suitesBundle)
if (oldView != null) {
oldView.saveSize()
ApplicationManager.getApplication().invokeLater {
val content = myContentManager!!.getContent(oldView)
runInEdt {
val manager = myContentManager ?: return@runInEdt
val content = manager.getContent(oldView)
if (content != null) {
myContentManager!!.removeContent(content, false)
manager.removeContent(content, false)
}
}
}
@@ -119,20 +114,30 @@ class CoverageViewManager(private val myProject: Project) : PersistentStateCompo
return getView(suitesBundle)
}
@Deprecated("Use activateToolwindow(CoverageView) instead", ReplaceWith("if (activate) activateToolwindow(view)"))
fun activateToolwindow(view: CoverageView, activate: Boolean) {
if (activate) {
activateToolwindow(view)
runInEdt {
activateToolwindow(view)
}
}
}
@Deprecated("Use createView instead", ReplaceWith("createView(suitesBundle, activate)"))
@RequiresEdt
fun createToolWindow(suitesBundle: CoverageSuitesBundle, activate: Boolean) {
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 }
}
class StateBean {
private var myFlattenPackages = false
@@ -204,12 +209,14 @@ class CoverageViewManager(private val myProject: Project) : PersistentStateCompo
}
companion object {
private val LOG = Logger.getInstance(CoverageViewManager::class.java)
const val TOOLWINDOW_ID: @NonNls String = "Coverage"
@JvmStatic
fun getInstance(project: Project): CoverageViewManager = project.service()
@JvmStatic
fun getInstanceIfCreated(project: Project): CoverageViewManager? = project.serviceIfCreated()
fun getDisplayName(suitesBundle: CoverageSuitesBundle): @NlsSafe String? {
val configuration = suitesBundle.runConfiguration
return configuration?.name ?: suitesBundle.presentableName

View File

@@ -29,12 +29,6 @@ public class CoverageViewSuiteListener implements CoverageSuiteListener {
myProject = project;
}
@Override
public void beforeSuiteChosen() {
// Call here to ensure that toolwindow is created
CoverageViewManager.getInstance(myProject);
}
@Override
public void coverageDataCalculated(@NotNull CoverageSuitesBundle suitesBundle) {
CoverageViewManager viewManager = CoverageViewManager.getInstance(myProject);

View File

@@ -7,6 +7,7 @@ import com.intellij.coverage.CoverageSuitesBundle;
import com.intellij.ide.SelectInContext;
import com.intellij.ide.SelectInTarget;
import com.intellij.ide.StandardTargetWeights;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -43,7 +44,7 @@ public final class SelectInCoverageView implements SelectInTarget {
final CoverageView coverageView = coverageViewManager.getView(suitesBundle);
coverageView.select(context.getVirtualFile());
if (requestFocus) {
coverageViewManager.activateToolwindow(coverageView);
ApplicationManager.getApplication().invokeLater(() -> coverageViewManager.activateToolwindow(coverageView));
}
}
}

View File

@@ -3,7 +3,7 @@ package com.intellij.coverage.view
import com.intellij.coverage.CoverageIntegrationBaseTest
import com.intellij.coverage.CoverageSuitesBundle
import com.intellij.openapi.wm.ToolWindowManager.Companion.getInstance
import com.intellij.openapi.wm.ToolWindowManager
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Test
@@ -19,6 +19,7 @@ class CoverageViewTest : CoverageIntegrationBaseTest() {
fun `test coverage toolwindow exists`() = runBlocking {
val bundle = loadIJSuite()
assertToolWindowDoesNotExist()
openSuiteAndWait(bundle)
assertToolWindowExists()
Assert.assertNotNull(findCoverageView(bundle))
@@ -33,6 +34,7 @@ class CoverageViewTest : CoverageIntegrationBaseTest() {
val ijSuite = loadIJSuite()
val xmlSuite = loadXMLSuite()
assertToolWindowDoesNotExist()
openSuiteAndWait(ijSuite)
assertToolWindowExists()
Assert.assertNotNull(findCoverageView(ijSuite))
@@ -54,10 +56,17 @@ class CoverageViewTest : CoverageIntegrationBaseTest() {
Assert.assertNull(findCoverageView(xmlSuite))
}
private fun findCoverageView(bundle: CoverageSuitesBundle): CoverageView? =
CoverageViewManager.getInstance(myProject).getToolwindow(bundle)
private fun assertToolWindowExists() {
Assert.assertNotNull(getInstance(myProject).getToolWindow(CoverageViewManager.TOOLWINDOW_ID))
@Test(timeout = TIMEOUT_MS)
fun `test call to service does not create tool window`() {
assertToolWindowDoesNotExist()
val manager = CoverageViewManager.getInstance(myProject)
assertToolWindowDoesNotExist()
manager.openedSuite
assertToolWindowDoesNotExist()
}
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())
}