execution_contexts.topic: Describe contexts for 2024.2+

This commit is contained in:
Karol Lewandowski 2025-02-19 18:01:37 +01:00 committed by Karol Lewandowski
parent fec5190b76
commit bbb7cadd37
7 changed files with 415 additions and 195 deletions

View File

@ -75,7 +75,7 @@
<toc-element topic="coroutine_dumps.md"/>
</toc-element>
<toc-element topic="background_processes.md"/>
<toc-element topic="execution_contexts.md" accepts-web-file-names="coroutine-execution-contexts.html"/>
<toc-element topic="execution_contexts.topic" accepts-web-file-names="coroutine-execution-contexts.html"/>
</toc-element>
<toc-element topic="messaging_infrastructure.md"/>
<toc-element toc-title="Queries and Query Executors"/>

View File

@ -19,7 +19,7 @@ Annotator
## B
Blocking Context
: Executing in the [blocking context](execution_contexts.md#blocking-context) means executing tasks on a thread without access to a coroutine context.
: Executing in the [blocking context](execution_contexts.topic#blocking-context) means executing tasks on a thread without access to a coroutine context.
&rarr;&nbsp;_Suspending Context_
&rarr;&nbsp;_Coroutine_
@ -130,7 +130,7 @@ Stubs
: A subset of a &rarr;&nbsp;_Program Structure Interface_ tree in a binary serialized compact format, see [](stub_indexes.md).
Suspending Context
: Executing in the [suspending context](execution_contexts.md#suspending-context-coroutines) means executing tasks in Kotlin coroutines.
: Executing in the [suspending context](execution_contexts.topic#suspending-context-coroutines) means executing tasks in Kotlin coroutines.
&rarr;&nbsp;_Blocking Context_
&rarr;&nbsp;_Coroutine_

View File

@ -14,7 +14,7 @@ The IntelliJ Platform executes background processes widely and provides two main
> Plugins targeting 2024.1+ should use [Kotlin coroutines](kotlin_coroutines.md), which is a more performant solution and provides the cancellation mechanism out of the box.
>
> See [](execution_contexts.md) for coroutine-based APIs to use in different contexts.
> See [](execution_contexts.topic) for coroutine-based APIs to use in different contexts.
>
{style="warning" title="Use Kotlin Coroutines"}

View File

@ -161,7 +161,7 @@ Sometimes it is not desired, as the coroutine in question was scheduled on [`Dis
Anyway, it is suspicious when a read action cannot be executed on a background thread and a part of coroutine code cannot be suspended and rescheduled on EDT.
This may signal a code issue.
Note that this API cannot be used in the [blocking context](execution_contexts.md#blocking-context).
Note that this API cannot be used in the [blocking context](execution_contexts.topic#blocking-context).
### Suspending `readAndWriteAction()`
@ -176,7 +176,7 @@ Consider rewriting code to use it, if possible.
Use them if a read action is required, but it is unacceptable to reschedule code execution on a different dispatcher.
These APIs are marked to use only in the [blocking context](execution_contexts.md#blocking-context), so their usage in the [suspending context](execution_contexts.md#suspending-context-coroutines) will trigger a warning.
These APIs are marked to use only in the [blocking context](execution_contexts.topic#blocking-context), so their usage in the [suspending context](execution_contexts.topic#suspending-context-coroutines) will trigger a warning.
It is intentional, as coroutines should be prepared to be rescheduled and should use `readAction()`.
### Suspending `writeIntentReadAction()` and Blocking `WriteIntentReadAction.run()`/`compute()`

View File

@ -1,188 +0,0 @@
<!-- Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
# Execution Contexts
<link-summary>Tracking execution progress, checking for cancellations, and switching between different execution contexts.</link-summary>
The IntelliJ Platform provides APIs that allow tracking the progress of background processes and canceling their execution when they are canceled by a user, or they become obsolete due to some changes in the data model.
Background processes can be executed in three contexts:
- [](#suspending-context-coroutines) — available since 2024.1
- [](#blocking-context)
- [](#progress-indicator) — obsolete since 2024.1
Currently, the Progress Indicator context is the most widely used approach in the IntelliJ Platform.
As the platform's execution model moves towards [coroutines](launching_coroutines.md), this approach can be considered obsolete.
Starting with 2024.1, it is recommended to execute new code in the [suspending context](#suspending-context-coroutines).
The following sections explain the contexts and provide information about process cancellation, progress tracking, and switching between different contexts.
## Suspending Context (Coroutines)
<primary-label ref="2024.1"/>
Code [executed in Kotlin coroutines](launching_coroutines.md) is executed in a suspending context.
Since 2024.1, this context is recommended for executing background tasks to maximize CPU utilization.
> Note that executing code in a suspending context is possible only with [Kotlin](using_kotlin.md).
>
{style="warning"}
In a suspending context, methods such as `ProgressManager.checkCanceled()` or `ModalityState.defaultModalityState()` won't have any effect.
Therefore, if their behavior is required, [switch to a blocking context](#switching-between-contexts).
> Inspection <control>Plugin DevKit | Code | Forbidden in suspend context method usage</control> reports calling blocking code from suspending context.
## Blocking Context
Executing tasks in a blocking context means executing them on a thread without access to the [coroutine context](#suspending-context-coroutines) (basically, in non-suspending functions) and not under [a progress indicator](#progress-indicator).
Such tasks can still be canceled, but they can't report progress.
Plugins should not execute new code in the blocking context.
Always prefer executing tasks in the [suspending context](#suspending-context-coroutines) or under the [progress indicator](#progress-indicator) if a plugin cannot use Kotlin.
> Functions which schedule execution via [`Application.executeOnPooledThread()`](%gh-ic%/platform/core-api/src/com/intellij/openapi/application/Application.java)
> and similar methods, and which rely on [`ProgressManager.checkCanceled()`](%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java)
> should be annotated with [`@RequiresBlockingContext`](%gh-ic%/platform/core-api/src/com/intellij/util/concurrency/annotations/RequiresBlockingContext.kt)
> to inform clients about the required switch to a blocking context.
>
> Inspection <control>Plugin DevKit | Code | Calling method should be annotated with @RequiresBlockingContext</control> reports missing annotations.
## Progress Indicator
<primary-label ref="obsolete-2024.1"/>
Code executed via the Progress API
([`ProgressManager`](%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java),
[`ProgressIndicator`](%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicator.java), etc.)
is executed in a progress indicator context.
See the [](background_processes.md#progress-api) section for details.
> Executing code under the progress indicator is obsolete since 2024.1.
> It is advised to use Kotlin coroutines in new code.
>
> Please note that obsolete status does not mean deprecation.
> Executing code using the Progress API is still allowed, but coroutines are recommended as a more performant solution.
>
{style="tip" title="Obsolete approach since 2024.1"}
## Execution Contexts APIs
### Cancellation Check
The following table presents APIs to use for checking whether a task was canceled in different execution contexts.
<table style="header-column">
<tr>
<td width="16%">Suspending</td>
<td>
<code><a href="https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/ensure-active.html">ensureActive()</a></code> from Kotlin coroutine's API
<warning>
Note that <code><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java">ProgressManager.checkCanceled()</a></code> does not work in a suspending context.
</warning>
</td>
</tr>
<tr>
<td>Blocking</td>
<td>
<code><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java">ProgressManager.checkCanceled()</a></code>
<p>See <a href="background_processes.md#cancellation">Background Processes: Cancellation</a> for details.</p>
</td>
</tr>
<tr>
<td>Progress&nbsp;Indicator</td>
<td>
<code><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicator.java">ProgressIndicator.checkCanceled()</a></code>, <code><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java">ProgressManager.checkCanceled()</a></code>
<p>See <a href="background_processes.md#cancellation">Background Processes: Cancellation</a> for details.</p>
</td>
</tr>
</table>
### Progress Reporting
The following table presents the possibilities and APIs to use for reporting progress in different execution contexts.
<table style="header-column">
<tr>
<td width="16%">Suspending</td>
<td>
<ul>
<li><code><a href="%gh-ic%/platform/util/progress/src/impl/ProgressStep.kt">ProgressStep</a></code> - a step-based progress reporting (see its KDoc for details)</li>
<li><code><a href="%gh-ic%/platform/util/progress/src/RawProgressReporter.kt">RawProgressReporter</a></code> - a raw text, details, and fraction reporting (invoked via <code><a href="%gh-ic%/platform/util/progress/src/steps.kt">reportRawProgress()</a></code>)</li>
</ul>
<p>
Any <code><a href="%gh-ic%/platform/util/progress/src/steps.kt">report*Progress()</a></code> function must be used inside <code>withBackgroundProgress()</code>, <code>withModalProgress()</code>, or <code>runWithModalProgressBlocking()</code> from <a href="%gh-ic%/platform/progress/shared/src/tasks.kt"><path>tasks.kt</path></a>.
Otherwise, if there is no reporter in the context, using <code>report*Progress()</code> will have no effect.
Example:
</p>
<code-block lang="kotlin">
withBackgroundProgress(...) { // or other
// ...
reportProgress { reporter -> // or another report*Progress
// do tasks and report progress
}
// ...
}
</code-block>
</td>
</tr>
<tr>
<td>Blocking</td>
<td>
unavailable
</td>
</tr>
<tr>
<td>Progress&nbsp;Indicator</td>
<td>
<a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicator.java"><code>ProgressIndicator</code>'s</a> or <a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java"><code>ProgressManager</code>'s</a> methods
<p>See <a href="background_processes.md#tracking-progress">Background Processes: Tracking Progress</a> for details.</p>
</td>
</tr>
</table>
### Switching Between Contexts
The following table presents the possibilities and APIs to use for switching between different execution contexts.
<table style="both">
<tr>
<td width="16%"></td>
<td>To&nbsp;Suspending</td>
<td>To&nbsp;Blocking</td>
<td>To&nbsp;Progress&nbsp;Indicator</td>
</tr>
<tr>
<td>From Suspending</td>
<td>-</td>
<td><code>blockingContext()</code> <sup>1</sup></td>
<td>unavailable <sup>3</sup></td>
</tr>
<tr>
<td>From Blocking</td>
<td><code>runBlockingCancellable()</code> <sup>2</sup></td>
<td>-</td>
<td>unavailable <sup>4</sup></td>
</tr>
<tr>
<td>From Progress&nbsp;Indicator</td>
<td><code>runBlockingCancellable()</code> <sup>2</sup></td>
<td>unavailable</td>
<td>-</td>
</tr>
<tr>
<td colspan="4">
<sup>1</sup> <i><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt"><code>blockingContext()</code></a> enables <code>ProgressManager.checkCanceled()</code>, forwards modality state, etc. It has an opposite behavior to <code>runBlockingCancellable()</code>.</i><br/>
<sup>2</sup> <i><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt"><code>runBlockingCancellable()</code></a> has an opposite behavior to <code>blockingContext()</code></i><br/>
<sup>3</sup> <i><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt"><code>coroutineToIndicator()</code></a> is an internal API to aid platform migration</i><br/>
<sup>4</sup> <i><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt"><code>blockingContextToIndicator()</code></a> is an internal API to aid platform migration</i>
</td>
</tr>
</table>
It is only possible to:
- switch from the blocking context or progress indicator to the suspending context
- switch from the suspending context to the blocking context
The lack of an API for switching from suspending and blocking contexts to progress indicator is intentional.
Cancellable and trackable tasks should be run in coroutines as the progress indicator is obsolete since 2024.1.
<include from="snippets.md" element-id="missingContent"/>

View File

@ -0,0 +1,408 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<!DOCTYPE topic SYSTEM "https://resources.jetbrains.com/writerside/1.0/xhtml-entities.dtd">
<topic xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://resources.jetbrains.com/writerside/1.0/topic.v2.xsd"
id="execution_contexts" title="Execution Contexts">
<title>Execution Contexts</title>
<link-summary>Tracking execution progress, checking for cancellations, and switching between different execution contexts.</link-summary>
<p>The IntelliJ Platform provides APIs that allow tracking the progress of background processes and canceling their
execution when they are canceled by a user, or they become obsolete due to some changes in the data model.</p>
<!--TODO: what if someone wants to support 2024.1 and 2024.2. Can they safely call blockingContext as it is no-op now?-->
<!--TODO: any caveats for progress reporting in Job context?-->
<p>Available execution contexts differ depending on the IntelliJ Platform version.
For the details, select the required tab below.</p>
<tabs group="execution-contexts">
<tab title="2024.2+" group-key="2024.2">
<p>Background processes can be executed in two contexts:</p>
<list>
<li><a anchor="job-context-coroutines"/> — available since 2024.2</li>
<li><a anchor="progress-indicator"/> — obsolete since 2024.1</li>
</list>
<p id="progress-indicator-migration-note">Currently, the Progress Indicator context is the most widely used approach in the IntelliJ Platform.
As the platform's execution model moves towards <a href="launching_coroutines.md">coroutines</a>, this approach
can be considered obsolete.</p>
<p>Starting with 2024.2, it is recommended to execute new code in the
<a anchor="job-context-coroutines">Job context</a>.</p>
<p id="sections-note">The following sections explain the contexts and provide information about process cancellation, progress
tracking, and switching between contexts.</p>
<!-- TODO: I'm not convinced the Job context is a good name. Suspending or Coroutine Context would be clearer, IHMO. -->
<chapter title="Job Context (Coroutines)" id="job-context-coroutines">
<primary-label ref="2024.2"/>
<tip>
Suspending and Blocking contexts available in 2024.1 have been unified into the Job context.
See the <a href="https://youtrack.jetbrains.com/issue/IJPL-445/Reconsider-blockingContext">
<i>Reconsider blockingContext</i></a> issue for more details.
</tip>
<p>Code <a href="launching_coroutines.md">executed in Kotlin coroutines</a> is executed in the Job context.
Since 2024.2, coroutines are recommended for executing background tasks to maximize CPU utilization.
Note that executing code in coroutines is possible only with <a href="using_kotlin.md">Kotlin</a>.
</p>
<p>
While code executed in the Job context should use suspending functions,
sometimes it is required to call non-suspending/blocking APIs that use methods such as
<code>ProgressManager.checkCanceled()</code> or <code>ModalityState.defaultModalityState()</code>.
Since 2024.2, these methods work as expected without the need to switch to the blocking context.
</p>
<tip>The "Job" word in the name refers to the
<a href="https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/">
<code>Job</code></a> class, which is used for task cancellation in suspending and non-suspending
functions.
</tip>
<tip>
<p>Inspection
<control>Plugin DevKit | Code | Forbidden in suspend context method usage</control>
reports calling blocking code from suspending context.
While this is not an error, it is recommended to use suspending counterparts if they exist.
</p>
</tip>
</chapter>
</tab>
<tab title="2024.1" group-key="2024.1">
<p>Background processes can be executed in three contexts:</p>
<list>
<li><a anchor="suspending-context-coroutines"/> — available since 2024.1</li>
<li><a anchor="blocking-context"/></li>
<li><a anchor="progress-indicator"/> — obsolete since 2024.1</li>
</list>
<include from="execution_contexts.topic" element-id="progress-indicator-migration-note"/>
<p>Starting with 2024.1, it is recommended to execute new code in the
<a anchor="suspending-context-coroutines">suspending context</a>.</p>
<include from="execution_contexts.topic" element-id="sections-note"/>
<chapter title="Suspending Context (Coroutines)" id="suspending-context-coroutines">
<primary-label ref="2024.1"/>
<p>Code <a href="launching_coroutines.md">executed in Kotlin coroutines</a> is executed in a suspending context.
Since 2024.1, this context is recommended for executing background tasks to maximize CPU utilization.
Note that executing code in coroutines is possible only with <a href="using_kotlin.md">Kotlin</a>.
</p>
<p>In a suspending context, methods such as <code>ProgressManager.checkCanceled()</code> or <code>ModalityState.defaultModalityState()</code>
won't have any effect.
Therefore, if their behavior is required, <a anchor="switching-between-contexts">switch to a blocking
context</a>.</p>
<tip>
<p>Inspection
<control>Plugin DevKit | Code | Forbidden in suspend context method usage</control>
reports calling blocking code from suspending context.
</p>
</tip>
</chapter>
<chapter title="Blocking Context" id="blocking-context">
<p>Executing tasks in a blocking context means executing them on a thread without access to the <a
anchor="suspending-context-coroutines">coroutine context</a> (basically, in non-suspending functions)
and not under <a anchor="progress-indicator">a progress indicator</a>.
Such tasks can still be canceled, but they can't report progress.</p>
<p>Plugins should not execute new code in the blocking context.
Always prefer executing tasks in the <a anchor="suspending-context-coroutines">suspending context</a> or
under the <a anchor="progress-indicator">progress indicator</a> if a plugin cannot use Kotlin.</p>
<tip>
<!--TODO: copy it to Job Context and state that it is used for choosing a better non-blocking API? revise what Daniil said -->
<p>Functions which schedule execution via <a
href="%gh-ic%/platform/core-api/src/com/intellij/openapi/application/Application.java"><code>Application.executeOnPooledThread()</code></a>
and similar methods, and which rely on <a
href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java"><code>ProgressManager.checkCanceled()</code></a>
should be annotated with <a
href="%gh-ic%/platform/core-api/src/com/intellij/util/concurrency/annotations/RequiresBlockingContext.kt"><code>@RequiresBlockingContext</code></a>
to inform clients about the required switch to a blocking context.</p>
<p>Inspection
<control>Plugin DevKit | Code | Calling method should be annotated with @RequiresBlockingContext
</control>
reports missing annotations.
</p>
</tip>
</chapter>
</tab>
</tabs>
<chapter title="Progress Indicator" id="progress-indicator">
<primary-label ref="obsolete-2024.1"/>
<p>Code executed via the Progress API
(<a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java"><code>ProgressManager</code></a>,
<a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicator.java"><code>ProgressIndicator</code></a>,
etc.)
is executed in a progress indicator context.
See the <a href="background_processes.md" anchor="progress-api"/> section for details.</p>
<tip title="Obsolete approach since 2024.1">
<p>Executing code under the progress indicator is obsolete since 2024.1.
It is advised to use Kotlin coroutines in new code.</p>
<p>Please note that obsolete status does not mean deprecation.
Executing code using the Progress API is still allowed, but coroutines are recommended as a more
performant solution.</p>
</tip>
</chapter>
<chapter title="Execution Contexts APIs" id="execution-contexts-apis">
<chapter title="Cancellation Check" id="cancellation-check">
<p>The following table presents APIs to use for checking whether a task was canceled in different execution
contexts.</p>
<tip>
See <a href="background_processes.md#cancellation">Background Processes: Cancellation</a> for
general cancellation mechanism explanation.
</tip>
<tabs group="execution-contexts">
<tab title="2024.2+" group-key="2024.2">
<table style="header-column">
<tr>
<td width="16%">Job Context</td>
<td>
<list>
<li><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt">
<code>checkCanceled()</code></a></li>
<li><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java">
<code>ProgressManager.checkCanceled()</code></a></li>
</list>
</td>
</tr>
<tr id="cancellation-check-progress-indicator-row">
<td>Progress&nbsp;Indicator</td>
<td>
<list>
<li><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicator.java">
<code>ProgressIndicator.checkCanceled()</code></a></li>
<li><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java">
<code>ProgressManager.checkCanceled()</code></a></li>
</list>
</td>
</tr>
</table>
</tab>
<tab title="2024.1" group-key="2024.1">
<table style="header-column">
<tr>
<td width="16%">Suspending Context</td>
<td>
<list>
<li><a href="https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/ensure-active.html"><code>ensureActive()</code></a>
from Kotlin coroutine's API</li>
</list>
<warning>
Note that
<a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java"><code>ProgressManager.checkCanceled()</code></a>
does not work in the suspending context.
To enable it,
<a anchor="switching-between-contexts">switch to <code>blockingContext()</code></a>,
if it is not possible to change the code.
</warning>
</td>
</tr>
<tr>
<td>Blocking Context</td>
<td>
<list>
<li><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java"><code>ProgressManager.checkCanceled()</code></a></li>
</list>
</td>
</tr>
<include from="execution_contexts.topic" element-id="cancellation-check-progress-indicator-row"/>
</table>
</tab>
</tabs>
</chapter>
<chapter title="Progress Reporting" id="progress-reporting">
<p>The following table presents the possibilities and APIs to use for reporting progress in different
execution contexts.</p>
<tabs group="execution-contexts">
<tab title="2024.2+" group-key="2024.2">
<table style="header-column">
<tr>
<td width="16%">Job Context</td>
<td id="progress-reporting-job-context-cell">
<list>
<li><a href="%gh-ic%/platform/util/progress/src/impl/ProgressStep.kt"><code>ProgressStep</code></a>
- a step-based progress reporting (see its KDoc for details)
</li>
<li><a href="%gh-ic%/platform/util/progress/src/RawProgressReporter.kt"><code>RawProgressReporter</code></a>
- a raw text, details, and fraction reporting (invoked via <a
href="%gh-ic%/platform/util/progress/src/steps.kt"><code>reportRawProgress()</code></a>)
</li>
</list>
<p>
Any <a href="%gh-ic%/platform/util/progress/src/steps.kt"><code>report*Progress()</code></a>
function must be used inside <code>withBackgroundProgress()</code>, <code>withModalProgress()</code>,
or <code>runWithModalProgressBlocking()</code> from <a
href="%gh-ic%/platform/progress/shared/src/tasks.kt">
<path>tasks.kt</path>
</a>.
Otherwise, if there is no reporter in the context, using <code>report*Progress()</code> will
have no effect.
Example:
</p>
<code-block lang="kotlin">
withBackgroundProgress(...) { // or other
// ...
reportProgress { reporter -> // or another report*Progress
// do tasks and report progress
}
// ...
}
</code-block>
</td>
</tr>
<tr id="progress-reporting-progress-indicator-row">
<td>Progress&nbsp;Indicator</td>
<td>
<a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicator.java"><code>ProgressIndicator</code>'s</a>
or <a
href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java"><code>ProgressManager</code>'s</a>
methods
<p>See <a href="background_processes.md#tracking-progress">Background Processes: Tracking
Progress</a> for details.</p>
</td>
</tr>
</table>
</tab>
<tab title="2024.1" group-key="2024.1">
<table style="header-column">
<tr>
<td width="16%">Suspending Context</td>
<include from="execution_contexts.topic" element-id="progress-reporting-job-context-cell"/>
</tr>
<tr>
<td>Blocking Context</td>
<td>
unavailable
</td>
</tr>
<include from="execution_contexts.topic" element-id="progress-reporting-progress-indicator-row"/>
</table>
</tab>
</tabs>
</chapter>
<chapter title="Switching Between Contexts" id="switching-between-contexts">
<p>The following table presents the possibilities and APIs to use for switching between different execution
contexts.</p>
<tabs group="execution-contexts">
<tab title="2024.2+" group-key="2024.2">
<table style="both">
<tr>
<td width="16%"/>
<td width="42%">To Job Context</td>
<td width="42%">To Progress Indicator</td>
</tr>
<tr>
<td>From Job Context</td>
<td>-</td>
<td><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt">
<code>coroutineToIndicator()</code></a> <sup>1</sup></td>
</tr>
<tr>
<td>From Progress&nbsp;Indicator</td>
<td><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt">
<code>runBlockingCancellable()</code></a></td>
<td>-</td>
</tr>
<tr>
<td colspan="4">
<sup>1</sup>
<i><code>coroutineToIndicator()</code>
is an experimental API, which was originally internal and created to aid
platform migration.
It is not recommended to switch from the Job context to the progress indicator.
Use it only if there is no other option.</i>
</td>
</tr>
</table>
</tab>
<tab title="2024.1" group-key="2024.1">
<table style="both">
<tr>
<td width="16%"/>
<td>To Suspending Context</td>
<td>To Blocking Context</td>
<td>To&nbsp;Progress&nbsp;Indicator</td>
</tr>
<tr>
<td>From Suspending Context</td>
<td>-</td>
<td><code>blockingContext()</code> <sup>1</sup></td>
<td>unavailable <sup>3</sup></td>
</tr>
<tr>
<td>From Blocking Context</td>
<td><code>runBlockingCancellable()</code> <sup>2</sup></td>
<td>-</td>
<td>unavailable <sup>4</sup></td>
</tr>
<tr>
<td>From Progress&nbsp;Indicator</td>
<td><code>runBlockingCancellable()</code> <sup>2</sup></td>
<td>unavailable</td>
<td>-</td>
</tr>
<tr>
<td colspan="4">
<sup>1</sup>
<i><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt">
<code>blockingContext()</code></a>
enables <code>ProgressManager.checkCanceled()</code>, forwards modality state, etc.
It has an opposite behavior to <code>runBlockingCancellable()</code>.
Since 2024.2, it is a no-operation function, as the blocking context was unified
with the suspending context into the Job context.</i>
<br/>
<sup>2</sup>
<i><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt">
<code>runBlockingCancellable()</code></a>
has an opposite behavior to <code>blockingContext()</code></i>
<br/>
<sup>3</sup>
<i><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt">
<code>coroutineToIndicator()</code></a>
is an internal API to aid platform migration</i>
<br/>
<sup>4</sup>
<i><a href="%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/coroutines.kt">
<code>blockingContextToIndicator()</code></a>
is an internal API to aid platform migration</i>
</td>
</tr>
</table>
<p>It is only possible to:</p>
<list>
<li>switch from the blocking context or progress indicator to the suspending context</li>
<li>switch from the suspending context to the blocking context</li>
</list>
<p>The lack of an API for switching from suspending and blocking contexts to progress indicator is
intentional.
Cancellable and trackable tasks should be run in coroutines as the progress indicator is obsolete since
2024.1.</p>
</tab>
</tabs>
<include from="snippets.md" element-id="missingContent"/>
</chapter>
</chapter>
</topic>
<!--TODO: glossary: Job context-->
<!--TODO: search for execution_context.topic and adjust dependant content-->
<!--TODO: add to content updates-->

View File

@ -6,7 +6,7 @@
<tldr>
**Implementation**: Progress tracking in [Progress API](background_processes.md#tracking-progress) and [Kotlin Coroutines](execution_contexts.md#progress-reporting)
**Implementation**: Progress tracking in [Progress API](background_processes.md#tracking-progress) and [Kotlin Coroutines](execution_contexts.topic#progress-reporting)
</tldr>