From ded6a8aab5edb13dc17f3734aadc553673243765 Mon Sep 17 00:00:00 2001 From: Konstantin Nisht Date: Fri, 5 Dec 2025 08:47:54 +0100 Subject: [PATCH] [actions] IJPL-221811: Use correct dispatcher for Action's coroutine scope GitOrigin-RevId: 0ab2955e3780829f62dcea34b5aeddc83988d166 --- .../intellij/openapi/actionSystem/impl/ActionManagerImpl.kt | 2 +- .../openapi/actionSystem/ActionCoroutineScopeTest.kt | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.kt b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.kt index 4e721995dcf4..85bc68cb5499 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.kt @@ -1160,7 +1160,7 @@ open class ActionManagerImpl protected constructor(private val coroutineScope: C ActionContextElement.create(actionId, event.place, event.inputEvent, component) // todo: remove `ThreadScopeCheckpoint` from here once we migrate all usages to `AnActionEvent#coroutineScope` val coroutineContext2 = coroutineContext + ThreadScopeCheckpoint(coroutineContext) // permit `currentThreadCoroutineScope` inside - val providedScope = cs.childScope("actionPerformed of $actionId", coroutineContext.minusKey(Job.Key)) + val providedScope = cs.childScope("actionPerformed of $actionId", coroutineContext.minusKey(Job.Key) + Dispatchers.Default) event.installCoroutineScope(providedScope) try { installThreadContext(coroutineContext2.minusKey(ContinuationInterceptor), replace = true) { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/actionSystem/ActionCoroutineScopeTest.kt b/platform/platform-tests/testSrc/com/intellij/openapi/actionSystem/ActionCoroutineScopeTest.kt index fb7bdef4aea5..6a23aaffb5bf 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/actionSystem/ActionCoroutineScopeTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/openapi/actionSystem/ActionCoroutineScopeTest.kt @@ -10,19 +10,23 @@ import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicReference @TestApplication class ActionCoroutineScopeTest { + @OptIn(ExperimentalStdlibApi::class) @Test fun `coroutineScope is available in actionPerformed`() = timeoutRunBlocking { val gotScope = AtomicBoolean(false) val jobRan = CompletableDeferred() + val scopeDispatcher = AtomicReference() val action = object : AnAction() { override fun actionPerformed(e: AnActionEvent) { val scope = e.coroutineScope gotScope.set(true) + scopeDispatcher.set(scope.coroutineContext[CoroutineDispatcher]) scope.launch { jobRan.complete(true) } @@ -39,6 +43,7 @@ class ActionCoroutineScopeTest { // Wait for the launched coroutine to run Assertions.assertTrue(jobRan.awaitWithTimeout(5, TimeUnit.SECONDS) == true, "Coroutine launched from action scope should run") + Assertions.assertTrue(scopeDispatcher.get() == Dispatchers.Default, "Coroutine scope dispatcher should be Dispatchers.Default") } @Test