[java] Fix the auto-test floating toolbar behavior

Auto-test is disabled:
- when another test configuration is started
- when the test configuration tab is closed

#IDEA-365697 Fixed
#IDEA-365668 Fixed


(cherry picked from commit 417cb8a692feda19ccb635c8732b52613a71b6b3)

IJ-CR-155896

GitOrigin-RevId: e0d3504cf063d588ef9d79cd3f8ecc290c52e4ec
This commit is contained in:
Louis Vignier
2025-02-21 18:43:28 +01:00
committed by intellij-monorepo-bot
parent c3b13e24d1
commit f6b80cf5c3
10 changed files with 75 additions and 57 deletions

View File

@@ -1,8 +1,17 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. // 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.execution.testDiscovery package com.intellij.execution.testDiscovery
import com.intellij.execution.testDiscovery.JavaAutoRunFloatingToolbarService.JavaAutoRunFloatingToolbarState import com.intellij.execution.ExecutionListener
import com.intellij.execution.ExecutionManager
import com.intellij.execution.process.ProcessHandler
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.execution.testframework.TestConsoleProperties
import com.intellij.execution.testframework.autotest.AutoTestListener import com.intellij.execution.testframework.autotest.AutoTestListener
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView
import com.intellij.execution.ui.ConsoleViewWithDelegate
import com.intellij.execution.ui.ExecutionConsole
import com.intellij.execution.ui.RunContentDescriptor
import com.intellij.execution.ui.RunContentManager
import com.intellij.icons.AllIcons import com.intellij.icons.AllIcons
import com.intellij.ide.IdeBundle import com.intellij.ide.IdeBundle
import com.intellij.java.JavaBundle import com.intellij.java.JavaBundle
@@ -10,12 +19,13 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.* import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.actionSystem.ex.CustomComponentAction import com.intellij.openapi.actionSystem.ex.CustomComponentAction
import com.intellij.openapi.actionSystem.impl.ActionButton import com.intellij.openapi.actionSystem.impl.ActionButton
import com.intellij.openapi.components.*
import com.intellij.openapi.editor.EditorKind import com.intellij.openapi.editor.EditorKind
import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent
import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarProvider import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarProvider
import com.intellij.openapi.editor.toolbar.floating.isInsideMainEditor import com.intellij.openapi.editor.toolbar.floating.isInsideMainEditor
import com.intellij.openapi.observable.util.whenDisposed
import com.intellij.openapi.project.DumbAware import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBLabel
import com.intellij.util.application import com.intellij.util.application
import com.intellij.util.ui.GridBag import com.intellij.util.ui.GridBag
@@ -31,6 +41,8 @@ import javax.swing.JPanel
@ApiStatus.Internal @ApiStatus.Internal
class JavaAutoRunFloatingToolbarProvider : FloatingToolbarProvider { class JavaAutoRunFloatingToolbarProvider : FloatingToolbarProvider {
private var configuration: RunContentDescriptor? = null
override val backgroundAlpha: Float = JBUI.CurrentTheme.FloatingToolbar.TRANSLUCENT_BACKGROUND_ALPHA override val backgroundAlpha: Float = JBUI.CurrentTheme.FloatingToolbar.TRANSLUCENT_BACKGROUND_ALPHA
override val autoHideable: Boolean = false override val autoHideable: Boolean = false
@@ -50,21 +62,47 @@ class JavaAutoRunFloatingToolbarProvider : FloatingToolbarProvider {
val autoRunManager = JavaAutoRunManager.getInstance(project) val autoRunManager = JavaAutoRunManager.getInstance(project)
application.invokeLater { application.invokeLater {
updateFloatingToolbarVisibility(component, autoRunManager) updateFloatingToolbarVisibility(project, component, autoRunManager)
} }
project.messageBus.connect(parentDisposable).subscribe(AutoTestListener.TOPIC, object: AutoTestListener { project.messageBus.connect(parentDisposable).subscribe(AutoTestListener.TOPIC, object: AutoTestListener {
override fun autoTestStatusChanged() { override fun autoTestStatusChanged() {
updateFloatingToolbarVisibility(component, autoRunManager) updateFloatingToolbarVisibility(project, component, autoRunManager)
// Picks up the current descriptor when auto-test is enabled (auto-test is always disabled on project opening)
updateCurrentConfiguration(project, autoRunManager, component)
} }
override fun autoTestSettingsChanged() { })
updateFloatingToolbarVisibility(component, autoRunManager)
// The descriptor is disposed and created again after each run.
project.messageBus.connect(parentDisposable).subscribe(ExecutionManager.EXECUTION_TOPIC, object : ExecutionListener {
override fun processStarted(executorId: String, env: ExecutionEnvironment, handler: ProcessHandler) {
updateCurrentConfiguration(project, autoRunManager, component)
} }
}) })
} }
private fun updateFloatingToolbarVisibility(component: FloatingToolbarComponent, autoRunManager: JavaAutoRunManager) { /**
val isToolbarEnabled = service<JavaAutoRunFloatingToolbarService>().toolbarEnabled * Keeps track of the current auto-run test descriptor.
*/
private fun updateCurrentConfiguration(project: Project, autoRunManager: JavaAutoRunManager, component: FloatingToolbarComponent) {
val content = RunContentManager.getInstance(project).getAllDescriptors().firstOrNull { autoRunManager.isAutoTestEnabled(it) }
if (content != configuration) { configuration = content; } else { return }
if (content == null) {
updateFloatingToolbarVisibility(project, component, autoRunManager)
return
}
content.whenDisposed {
updateFloatingToolbarVisibility(project, component, autoRunManager)
}
getConsoleProperties(project)?.addListener(TestConsoleProperties.SHOW_AUTO_TEST_TOOLBAR) {
updateFloatingToolbarVisibility(project, component, autoRunManager)
}
}
private fun updateFloatingToolbarVisibility(project: Project, component: FloatingToolbarComponent, autoRunManager: JavaAutoRunManager) {
val isToolbarEnabled = isAutoTestToolbarEnabled(project)
val hasEnabledAutoTests = autoRunManager.hasEnabledAutoTests() val hasEnabledAutoTests = autoRunManager.hasEnabledAutoTests()
if (isToolbarEnabled && hasEnabledAutoTests) { if (isToolbarEnabled && hasEnabledAutoTests) {
component.autoHideable = true component.autoHideable = true
@@ -103,7 +141,9 @@ private class DisableAction : AnAction(IdeBundle.message("button.disable"), Java
private class HideAction : AnAction() { private class HideAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) { override fun actionPerformed(e: AnActionEvent) {
application.service<JavaAutoRunFloatingToolbarService>().toolbarEnabled = false val project = e.project ?: return
val properties = getConsoleProperties(project) ?: return
TestConsoleProperties.SHOW_AUTO_TEST_TOOLBAR.set(properties, false)
} }
override fun getActionUpdateThread() = ActionUpdateThread.EDT override fun getActionUpdateThread() = ActionUpdateThread.EDT
@@ -113,26 +153,25 @@ private class HideAction : AnAction() {
} }
} }
private fun getContentDescriptor(project: Project): RunContentDescriptor? {
return RunContentManager.getInstanceIfCreated(project)?.selectedContent
}
@Service(Service.Level.APP) private fun getConsoleProperties(project: Project): TestConsoleProperties? {
@State(name = "JavaAutoRunFloatingToolbarSettings", storages = [Storage(StoragePathMacros.NON_ROAMABLE_FILE)]) val content = getContentDescriptor(project) ?: return null
internal class JavaAutoRunFloatingToolbarService : SimplePersistentStateComponent<JavaAutoRunFloatingToolbarState>( val console = getSMTRunnerConsoleView(content.executionConsole) ?: return null
JavaAutoRunFloatingToolbarState() return console.properties
) { }
private val messageBusPublisher by lazy {
application.messageBus.syncPublisher(AutoTestListener.TOPIC)
}
var toolbarEnabled: Boolean private fun isAutoTestToolbarEnabled(project: Project): Boolean {
get() = state.toolbarEnabled val properties = getConsoleProperties(project) ?: return false
set(value) { return TestConsoleProperties.SHOW_AUTO_TEST_TOOLBAR.get(properties)
if (value != state.toolbarEnabled) { }
state.toolbarEnabled = value
messageBusPublisher.autoTestSettingsChanged()
}
}
class JavaAutoRunFloatingToolbarState() : BaseState() { private fun getSMTRunnerConsoleView(console: ExecutionConsole): SMTRunnerConsoleView? {
var toolbarEnabled by property(true) return when (console) {
is SMTRunnerConsoleView -> console
is ConsoleViewWithDelegate -> getSMTRunnerConsoleView(console.delegate)
else -> null
} }
} }

View File

@@ -1,23 +0,0 @@
// 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.execution.testDiscovery
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.ToggleAction
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAware
class JavaAutoRunToggleFloatingToolbarAction: ToggleAction(), DumbAware {
override fun getActionUpdateThread(): ActionUpdateThread {
return ActionUpdateThread.BGT
}
override fun isSelected(e: AnActionEvent): Boolean {
return service<JavaAutoRunFloatingToolbarService>().toolbarEnabled
}
override fun setSelected(e: AnActionEvent, state: Boolean) {
val service = service<JavaAutoRunFloatingToolbarService>()
service.toolbarEnabled = state
}
}

View File

@@ -710,7 +710,6 @@ action.ResolveAllRepositoryLibraries.text=Resolve All Maven Libraries
action.ParseSdkmanrcAction.text=Update Project JDK action.ParseSdkmanrcAction.text=Update Project JDK
action.DownloadJdkAction.text=Download JDK\u2026 action.DownloadJdkAction.text=Download JDK\u2026
action.AddJdkAction.text=Add JDK from Disk\u2026 action.AddJdkAction.text=Add JDK from Disk\u2026
action.JavaAutoRunToggleFloatingToolbarAction.text=Show Auto Run Status in the Editor
library.depends.on.ide.title=Dependency on JARs from the IDE installation library.depends.on.ide.title=Dependency on JARs from the IDE installation
library.depends.on.ide.message=Library {0} uses JARs from the IDE installation. It might break if JAR is removed from a future version of the IDE. {1} library.depends.on.ide.message=Library {0} uses JARs from the IDE installation. It might break if JAR is removed from a future version of the IDE. {1}

View File

@@ -2819,10 +2819,6 @@
<action id="DownloadJdkAction" class="com.intellij.ide.actions.DownloadJdkAction" icon="AllIcons.Actions.Download"/> <action id="DownloadJdkAction" class="com.intellij.ide.actions.DownloadJdkAction" icon="AllIcons.Actions.Download"/>
<action id="AddJdkAction" class="com.intellij.ide.actions.AddJdkAction" icon="AllIcons.Nodes.PpJdk"/> <action id="AddJdkAction" class="com.intellij.ide.actions.AddJdkAction" icon="AllIcons.Nodes.PpJdk"/>
<action id="JavaAutoRunToggleFloatingToolbarAction" class="com.intellij.execution.testDiscovery.JavaAutoRunToggleFloatingToolbarAction">
<add-to-group group-id="ToolbarPanel.MoreActions" anchor="last"/>
</action>
</actions> </actions>
<actions resource-bundle="messages.JavaBundle"> <actions resource-bundle="messages.JavaBundle">

View File

@@ -131,6 +131,8 @@ junit.running.info.tests.failed.label=Tests Failed
junit.running.info.tests.failed.with.test.name.label=Tests Failed {0} junit.running.info.tests.failed.with.test.name.label=Tests Failed {0}
junit.running.info.tests.passed.label=Tests Passed junit.running.info.tests.passed.label=Tests Passed
junit.running.info.tests.passed.with.test.name.label=Tests Passed {0} junit.running.info.tests.passed.with.test.name.label=Tests Passed {0}
junit.running.info.show.auto.test.status.text=Show Auto-Test Status in the Editor
junit.running.info.show.auto.test.status.description=Enables the auto-test status floating toolbar in the editor
junit.run.hide.passed.action.name=Show Passed junit.run.hide.passed.action.name=Show Passed
junit.run.hide.passed.action.description=Show passed tests junit.run.hide.passed.action.description=Show passed tests
junit.runing.info.track.test.action.name=Track Running Test junit.runing.info.track.test.action.name=Track Running Test

View File

@@ -125,6 +125,7 @@ a:com.intellij.execution.testframework.TestConsoleProperties
- sf:SCROLL_TO_SOURCE:com.intellij.util.config.BooleanProperty - sf:SCROLL_TO_SOURCE:com.intellij.util.config.BooleanProperty
- sf:SCROLL_TO_STACK_TRACE:com.intellij.util.config.BooleanProperty - sf:SCROLL_TO_STACK_TRACE:com.intellij.util.config.BooleanProperty
- sf:SELECT_FIRST_DEFECT:com.intellij.util.config.BooleanProperty - sf:SELECT_FIRST_DEFECT:com.intellij.util.config.BooleanProperty
- sf:SHOW_AUTO_TEST_TOOLBAR:com.intellij.util.config.BooleanProperty
- sf:SHOW_INLINE_STATISTICS:com.intellij.util.config.BooleanProperty - sf:SHOW_INLINE_STATISTICS:com.intellij.util.config.BooleanProperty
- sf:SHOW_STATISTICS:com.intellij.util.config.BooleanProperty - sf:SHOW_STATISTICS:com.intellij.util.config.BooleanProperty
- sf:SORT_ALPHABETICALLY:com.intellij.util.config.BooleanProperty - sf:SORT_ALPHABETICALLY:com.intellij.util.config.BooleanProperty

View File

@@ -54,6 +54,7 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp
public static final BooleanProperty SHOW_INLINE_STATISTICS = new BooleanProperty("showInlineStatistics", true); public static final BooleanProperty SHOW_INLINE_STATISTICS = new BooleanProperty("showInlineStatistics", true);
public static final BooleanProperty INCLUDE_NON_STARTED_IN_RERUN_FAILED = new BooleanProperty("includeNonStarted", true); public static final BooleanProperty INCLUDE_NON_STARTED_IN_RERUN_FAILED = new BooleanProperty("includeNonStarted", true);
public static final BooleanProperty HIDE_SUCCESSFUL_CONFIG = new BooleanProperty("hideConfig", false); public static final BooleanProperty HIDE_SUCCESSFUL_CONFIG = new BooleanProperty("hideConfig", false);
public static final BooleanProperty SHOW_AUTO_TEST_TOOLBAR = new BooleanProperty("autoTestToolbar", true);
private final Project myProject; private final Project myProject;
private final Executor myExecutor; private final Executor myExecutor;

View File

@@ -163,6 +163,9 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab
secondaryGroup.add(myScrollToSource); secondaryGroup.add(myScrollToSource);
secondaryGroup.add(new AdjustAutotestDelayActionGroup()); secondaryGroup.add(new AdjustAutotestDelayActionGroup());
secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.running.info.show.auto.test.status.text"),
ExecutionBundle.message("junit.running.info.show.auto.test.status.description"),
null, properties, TestConsoleProperties.SHOW_AUTO_TEST_TOOLBAR));
secondaryGroup.addSeparator(); secondaryGroup.addSeparator();
secondaryGroup.add(new DumbAwareToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.select.first.failed.action.name"), secondaryGroup.add(new DumbAwareToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.select.first.failed.action.name"),
null, null, properties, TestConsoleProperties.SELECT_FIRST_DEFECT)); null, null, properties, TestConsoleProperties.SELECT_FIRST_DEFECT));

View File

@@ -155,7 +155,8 @@ public abstract class AbstractAutoTestManager implements PersistentStateComponen
return ContainerUtil.exists(RunContentManager.getInstance(myProject).getAllDescriptors(), this::isAutoTestEnabled); return ContainerUtil.exists(RunContentManager.getInstance(myProject).getAllDescriptors(), this::isAutoTestEnabled);
} }
boolean isAutoTestEnabled(@NotNull RunContentDescriptor descriptor) { @ApiStatus.Internal
public boolean isAutoTestEnabled(@NotNull RunContentDescriptor descriptor) {
ExecutionEnvironment environment = getCurrentEnvironment(descriptor); ExecutionEnvironment environment = getCurrentEnvironment(descriptor);
return environment != null && myEnabledRunProfiles.contains(environment.getRunProfile()); return environment != null && myEnabledRunProfiles.contains(environment.getRunProfile());
} }

View File

@@ -7,7 +7,6 @@ import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal @ApiStatus.Internal
interface AutoTestListener { interface AutoTestListener {
fun autoTestStatusChanged() fun autoTestStatusChanged()
fun autoTestSettingsChanged()
companion object { companion object {
@Topic.ProjectLevel @Topic.ProjectLevel