diff --git a/platform/core-api/api-dump.txt b/platform/core-api/api-dump.txt index 39d3fc684fe3..a6877507e0f3 100644 --- a/platform/core-api/api-dump.txt +++ b/platform/core-api/api-dump.txt @@ -1745,6 +1745,8 @@ com.intellij.util.QueryExecutor com.intellij.util.QueryParameters - getProject():com.intellij.openapi.project.Project - isQueryValid():Z +f:com.intellij.util.concurrency.ThreadingAssertions +- s:softAssertNoReadAccess():V com.intellij.util.download.DownloadableFileDescription - a:generateFileName(com.intellij.openapi.util.Condition):java.lang.String - a:getDefaultFileName():java.lang.String diff --git a/platform/core-api/src/com/intellij/util/concurrency/ThreadingAssertions.java b/platform/core-api/src/com/intellij/util/concurrency/ThreadingAssertions.java index 3dd0ea04fca6..bfc9702d0030 100644 --- a/platform/core-api/src/com/intellij/util/concurrency/ThreadingAssertions.java +++ b/platform/core-api/src/com/intellij/util/concurrency/ThreadingAssertions.java @@ -178,6 +178,19 @@ public final class ThreadingAssertions { } } + /** + * Asserts that the current thread has no read access without throwing an exception. + * + * @see com.intellij.util.concurrency.annotations.RequiresReadLockAbsence + */ + @Obsolete + public static void softAssertNoReadAccess() { + Application application = ApplicationManager.getApplication(); + if (application != null && application.isReadAccessAllowed()) { + getLogger().error(createThreadAccessException(MUST_NOT_EXECUTE_IN_READ_ACTION)); + } + } + /** * Asserts that the current thread has no read access local to this thread (non-inherited). */ diff --git a/platform/execution-impl/src/com/intellij/terminal/ui/TerminalWidget.kt b/platform/execution-impl/src/com/intellij/terminal/ui/TerminalWidget.kt index 37069b482815..ff7e696091fc 100644 --- a/platform/execution-impl/src/com/intellij/terminal/ui/TerminalWidget.kt +++ b/platform/execution-impl/src/com/intellij/terminal/ui/TerminalWidget.kt @@ -78,8 +78,8 @@ interface TerminalWidget : ComponentContainer { * so it is prohibited to call it on EDT or under read action. */ @ApiStatus.Experimental - @RequiresReadLockAbsence - @RequiresBackgroundThread + @RequiresReadLockAbsence(generateAssertion = false) + @RequiresBackgroundThread(generateAssertion = false) fun isCommandRunning(): Boolean { return false } diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/ShellTerminalWidget.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/ShellTerminalWidget.java index ac3b6167fad6..ba1c94982a37 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/ShellTerminalWidget.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/ShellTerminalWidget.java @@ -207,8 +207,8 @@ public class ShellTerminalWidget extends JBTerminalWidget implements TerminalPan * so it is prohibited to call it on EDT or under read action. */ @Override - @RequiresReadLockAbsence - @RequiresBackgroundThread + @RequiresReadLockAbsence(generateAssertion = false) + @RequiresBackgroundThread(generateAssertion = false) public boolean hasRunningCommands() throws IllegalStateException { TtyConnector connector = getTtyConnector(); if (connector == null) return false; diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalUtil.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalUtil.java index a5990a094be0..2cd085d95cb7 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalUtil.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalUtil.java @@ -12,6 +12,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.remote.RemoteSshProcess; import com.intellij.ui.ExperimentalUI; +import com.intellij.util.concurrency.ThreadingAssertions; import com.intellij.util.concurrency.annotations.RequiresBackgroundThread; import com.intellij.util.concurrency.annotations.RequiresReadLockAbsence; import com.intellij.util.containers.ContainerUtil; @@ -44,9 +45,13 @@ public final class TerminalUtil { * This method may access the file system and launch external processes, * so it is prohibited to call it on EDT or under read action. */ - @RequiresReadLockAbsence - @RequiresBackgroundThread + @SuppressWarnings("UsagesOfObsoleteApi") // Can't use just only annotations because they generate throwing assertions + @RequiresReadLockAbsence(generateAssertion = false) + @RequiresBackgroundThread(generateAssertion = false) public static boolean hasRunningCommands(@NotNull TtyConnector connector) throws IllegalStateException { + ThreadingAssertions.softAssertBackgroundThread(); + ThreadingAssertions.softAssertNoReadAccess(); + if (!connector.isConnected()) return false; ProcessTtyConnector processTtyConnector = ShellTerminalWidget.getProcessTtyConnector(connector); if (processTtyConnector == null) return true;