diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/incomplete/IncompleteModelHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/incomplete/IncompleteModelHighlightingTest.java index 0b38acef122c..902078d9b892 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/incomplete/IncompleteModelHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/incomplete/IncompleteModelHighlightingTest.java @@ -5,6 +5,8 @@ import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.project.IncompleteDependenciesService; +import static com.intellij.openapi.project.IncompleteDependenciesServiceKt.asAutoCloseable; + public final class IncompleteModelHighlightingTest extends LightDaemonAnalyzerTestCase { static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/incompleteHighlighting"; @@ -13,12 +15,12 @@ public final class IncompleteModelHighlightingTest extends LightDaemonAnalyzerTe } private void doTest(String fileName) { - var ignored = WriteAction.compute(() -> getProject().getService(IncompleteDependenciesService.class).enterIncompleteState()); - try { + IncompleteDependenciesService service = getProject().getService(IncompleteDependenciesService.class); + try (var ignored = asAutoCloseable(WriteAction.compute(() -> service.enterIncompleteState()))) { doTest(BASE_PATH + "/" + fileName, true, true); } - finally { - WriteAction.run(ignored::close); + catch (Exception e) { + throw new RuntimeException(e); } } diff --git a/platform/core-api/src/com/intellij/openapi/project/IncompleteDependenciesService.kt b/platform/core-api/src/com/intellij/openapi/project/IncompleteDependenciesService.kt index 729a67b5141d..e034f53a2f4a 100644 --- a/platform/core-api/src/com/intellij/openapi/project/IncompleteDependenciesService.kt +++ b/platform/core-api/src/com/intellij/openapi/project/IncompleteDependenciesService.kt @@ -1,7 +1,9 @@ // 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.openapi.project -import com.intellij.openapi.application.AccessToken +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.project.IncompleteDependenciesService.IncompleteDependenciesAccessToken +import com.intellij.util.concurrency.annotations.RequiresBlockingContext import com.intellij.util.concurrency.annotations.RequiresReadLock import com.intellij.util.concurrency.annotations.RequiresWriteLock import kotlinx.coroutines.flow.Flow @@ -30,8 +32,20 @@ interface IncompleteDependenciesService { INCOMPLETE(false) } - abstract class IncompleteDependenciesAccessToken : AccessToken() { + abstract class IncompleteDependenciesAccessToken { @RequiresWriteLock - abstract override fun finish() + abstract fun finish() + } +} + +@ApiStatus.Internal +fun IncompleteDependenciesAccessToken.asAutoCloseable(): AutoCloseable = WriteActionAutoCloseable(this::finish) + +private class WriteActionAutoCloseable(private val finish: () -> Unit) : AutoCloseable { + @RequiresBlockingContext + override fun close() { + ApplicationManager.getApplication().runWriteAction { + finish() + } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/IncompleteDependenciesServiceImpl.kt b/platform/platform-impl/src/com/intellij/openapi/project/IncompleteDependenciesServiceImpl.kt index a370a841d97f..aa3763ba61c3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/IncompleteDependenciesServiceImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/project/IncompleteDependenciesServiceImpl.kt @@ -1,7 +1,6 @@ // 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.openapi.project -import com.intellij.openapi.application.AccessToken import com.intellij.openapi.project.IncompleteDependenciesService.DependenciesState import com.intellij.openapi.project.IncompleteDependenciesService.IncompleteDependenciesAccessToken import com.intellij.util.concurrency.ThreadingAssertions @@ -14,7 +13,7 @@ import org.jetbrains.annotations.ApiStatus @ApiStatus.Internal class IncompleteDependenciesServiceImpl : IncompleteDependenciesService { override val stateFlow = MutableStateFlow(DependenciesState.COMPLETE) - private val tokens = HashSet() + private val tokens = HashSet() @RequiresReadLock override fun getState(): DependenciesState { @@ -35,7 +34,7 @@ class IncompleteDependenciesServiceImpl : IncompleteDependenciesService { } @RequiresWriteLock - private fun registerToken(token: AccessToken) { + private fun registerToken(token: IncompleteDependenciesAccessToken) { ThreadingAssertions.assertWriteAccess() // @RequiresWriteLock does nothing in Kotlin synchronized(tokens) { val wasEmpty = tokens.isEmpty() @@ -47,7 +46,7 @@ class IncompleteDependenciesServiceImpl : IncompleteDependenciesService { } @RequiresWriteLock - private fun deregisterToken(token: AccessToken) { + private fun deregisterToken(token: IncompleteDependenciesAccessToken) { ThreadingAssertions.assertWriteAccess() // @RequiresWriteLock does nothing in Kotlin synchronized(tokens) { tokens.remove(token) diff --git a/plugins/lombok/src/test/java/com/intellij/java/lomboktest/LombokIncompleteModeHighlightingTest.java b/plugins/lombok/src/test/java/com/intellij/java/lomboktest/LombokIncompleteModeHighlightingTest.java index a94b50a36dc2..dbed7480d402 100644 --- a/plugins/lombok/src/test/java/com/intellij/java/lomboktest/LombokIncompleteModeHighlightingTest.java +++ b/plugins/lombok/src/test/java/com/intellij/java/lomboktest/LombokIncompleteModeHighlightingTest.java @@ -7,6 +7,8 @@ import com.intellij.testFramework.PlatformTestUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import static com.intellij.openapi.project.IncompleteDependenciesServiceKt.asAutoCloseable; + public class LombokIncompleteModeHighlightingTest extends LightDaemonAnalyzerTestCase { public void testLombokBasics() { doTest(); } @@ -18,12 +20,12 @@ public class LombokIncompleteModeHighlightingTest extends LightDaemonAnalyzerTes } private void doTest(String fileName) { - var ignored = WriteAction.compute(() -> getProject().getService(IncompleteDependenciesService.class).enterIncompleteState()); - try { + IncompleteDependenciesService service = getProject().getService(IncompleteDependenciesService.class); + try (var ignored = asAutoCloseable(WriteAction.compute(() -> service.enterIncompleteState()))) { doTest("/plugins/lombok/testData/highlightingIncompleteMode/" + fileName, true, true); } - finally { - WriteAction.run(ignored::close); + catch (Exception e) { + throw new RuntimeException(e); } }