ensure TextHighlightingPass is instantiated in the BGT under DaemonIndicator with corresponding HighlightingSession, to make (implicit)contracts more explicit, visible and simple

GitOrigin-RevId: f732af4b2bf614e6fca8c6af655beae34dfdcfc6
This commit is contained in:
Alexey Kudravtsev
2024-07-29 12:20:09 +02:00
committed by intellij-monorepo-bot
parent bba9f96b1f
commit e7c2f9831b
10 changed files with 71 additions and 29 deletions

View File

@@ -25,6 +25,15 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
/**
* The highlighting pass which is associated with {@link Document} and its markup model.
* The instantiation of this class must happen in the background thread, under {@link com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator}
* which has corresponding {@link com.intellij.codeInsight.daemon.impl.HighlightingSession}.
* It's discouraged to do all that manually, please register your {@link TextEditorHighlightingPassFactory} in plugin.xml instead, e.g. like this:
* <pre>
* {@code <highlightingPassFactory implementation="com.a.b.MyPassFactory"/>}
* </pre>
*/
public abstract class TextEditorHighlightingPass implements HighlightingPass {
public static final TextEditorHighlightingPass[] EMPTY_ARRAY = new TextEditorHighlightingPass[0];
protected final @NotNull Document myDocument;
@@ -44,6 +53,7 @@ public abstract class TextEditorHighlightingPass implements HighlightingPass {
myRunIntentionPassAfter = runIntentionPassAfter;
myInitialDocStamp = document.getModificationStamp();
myInitialPsiStamp = PsiModificationTracker.getInstance(project).getModificationCount();
ThreadingAssertions.assertBackgroundThread();
}
protected TextEditorHighlightingPass(@NotNull Project project, @NotNull Document document) {
this(project, document, true);

View File

@@ -29,6 +29,7 @@ import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashingStrategy;
@@ -272,6 +273,7 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G
protected void notifyInspectionsFinished(@NotNull AnalysisScope scope) {
}
@RequiresBackgroundThread
public void performInspectionsWithProgress(@NotNull AnalysisScope scope, boolean runGlobalToolsOnly, boolean isOfflineInspections) {
myProgressIndicator = ProgressManager.getInstance().getProgressIndicator();
if (!(myProgressIndicator instanceof ProgressIndicatorEx) || !(myProgressIndicator instanceof ProgressIndicatorWithDelayedPresentation)) {
@@ -311,6 +313,7 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G
}
@RequiresBackgroundThread
protected void runTools(@NotNull AnalysisScope scope, boolean runGlobalToolsOnly, boolean isOfflineInspections) {
}

View File

@@ -21,6 +21,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.SystemProperties;
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NotNull;
@@ -59,6 +60,7 @@ public class GlobalInspectionContextEx extends GlobalInspectionContextBase {
public GlobalInspectionContextEx(@NotNull Project project) { super(project); }
@RequiresBackgroundThread
public void launchInspectionsOffline(@NotNull AnalysisScope scope,
@NotNull Path outputPath,
boolean runGlobalToolsOnly,
@@ -66,6 +68,7 @@ public class GlobalInspectionContextEx extends GlobalInspectionContextBase {
performInspectionsWithProgressAndExportResults(scope, runGlobalToolsOnly, true, outputPath, inspectionsResults);
}
@RequiresBackgroundThread
public void performInspectionsWithProgressAndExportResults(@NotNull AnalysisScope scope,
boolean runGlobalToolsOnly,
boolean isOfflineInspections,

View File

@@ -22,6 +22,8 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.impl.ProgressRunner;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.progress.util.ProgressIndicatorWithDelayedPresentation;
import com.intellij.openapi.project.DumbService;
@@ -665,19 +667,27 @@ public class InspectionApplicationBase implements CommandLineInspectionProgressR
@NotNull AnalysisScope scope,
@NotNull Path resultsDataPath,
@NotNull List<? super Path> inspectionsResults) {
ProgressManager.getInstance().runProcess(() -> {
configureProject(projectPath, project, scope);
Task.Backgroundable task = new Task.Backgroundable(project, "") {
@Override
public void run(@NotNull ProgressIndicator indicator) {
configureProject(projectPath, project, scope);
if (!GlobalInspectionContextUtil.canRunInspections(project, false, () -> {
})) {
onFailure(InspectionsBundle.message("inspection.application.cannot.configure.project.to.run.inspections"));
if (!GlobalInspectionContextUtil.canRunInspections(project, false, () -> {
})) {
onFailure(InspectionsBundle.message("inspection.application.cannot.configure.project.to.run.inspections"));
}
context.launchInspectionsOffline(scope, resultsDataPath, myRunGlobalToolsOnly, inspectionsResults);
reportMessage(1, "\n" + InspectionsBundle.message("inspection.capitalized.done") + "\n");
if (!myErrorCodeRequired) {
closeProject(project);
}
}
context.launchInspectionsOffline(scope, resultsDataPath, myRunGlobalToolsOnly, inspectionsResults);
reportMessage(1, "\n" + InspectionsBundle.message("inspection.capitalized.done") + "\n");
if (!myErrorCodeRequired) {
closeProject(project);
}
}, createProgressIndicator());
};
new ProgressRunner<>(task)
.onThread(ProgressRunner.ThreadToUse.POOLED)
.withProgress(createProgressIndicator())
.sync()
.submitAndGet();
}
private @NotNull ProgressIndicatorBase createProgressIndicator() {

View File

@@ -7,6 +7,7 @@ import com.intellij.codeInsight.hints.InlayGroup
import com.intellij.codeInsight.hints.declarative.*
import com.intellij.codeInsight.hints.settings.InlayProviderSettingsModel
import com.intellij.lang.Language
import com.intellij.openapi.actionSystem.ex.ActionUtil
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileTypes.FileType
@@ -111,7 +112,8 @@ class DeclarativeHintsProviderSettingsModel(
isEnabled
}
val pass = DeclarativeInlayHintsPass(file, editor, listOf(InlayProviderPassInfo(object : InlayHintsProvider {
val pass = ActionUtil.underModalProgress(project, "") {
DeclarativeInlayHintsPass(file, editor, listOf(InlayProviderPassInfo(object : InlayHintsProvider {
override fun createCollector(file: PsiFile, editor: Editor): InlayHintsCollector {
return object: OwnBypassCollector {
override fun collectHintsForFile(file: PsiFile, sink: InlayTreeSink) {
@@ -125,7 +127,7 @@ class DeclarativeHintsProviderSettingsModel(
}
}
}, providerId, enabledOptions)), false, !enabled)
}
pass.doCollectInformation(EmptyProgressIndicator())
return Runnable {

View File

@@ -78,6 +78,7 @@ import com.intellij.ui.content.ContentManager;
import com.intellij.util.*;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.intellij.util.concurrency.ThreadingAssertions;
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import io.opentelemetry.api.trace.Span;
@@ -279,6 +280,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextEx {
}
@Override
@RequiresBackgroundThread
protected void runTools(@NotNull AnalysisScope scope, boolean runGlobalToolsOnly, boolean isOfflineInspections) {
IJTracer tracer = TelemetryManager.getInstance().getTracer(GlobalInspectionScopeKt.GlobalInspectionScope);
runToolsSpan = tracer.spanBuilder("globalInspections").setNoParent().startSpan();
@@ -287,9 +289,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextEx {
if (!(progressIndicator instanceof ProgressIndicatorWithDelayedPresentation)) {
throw new IncorrectOperationException("Must be run under ProgressWindow");
}
if (!isOfflineInspections) {
ApplicationManager.getApplication().assertIsNonDispatchThread();
}
ApplicationManager.getApplication().assertIsNonDispatchThread();
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
throw new IncorrectOperationException("Must not start inspections from within write action");
}

View File

@@ -5,6 +5,7 @@ import com.intellij.codeInsight.hints.presentation.RecursivelyUpdatingRootPresen
import com.intellij.codeInsight.hints.presentation.RootInlayPresentation
import com.intellij.codeInsight.hints.presentation.SpacePresentation
import com.intellij.lang.Language
import com.intellij.openapi.actionSystem.ex.ActionUtil
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.Inlay
import com.intellij.openapi.progress.DumbProgressIndicator
@@ -178,7 +179,8 @@ class InlayPassTest : BasePlatformTestCase() {
}
private fun createPass(collectors: List<CollectorWithSettings<*>>): InlayHintsPass {
return InlayHintsPass(myFixture.file, collectors, myFixture.editor, myFixture.editor.calculateVisibleRange(), sharedSink)
val visibleRange = myFixture.editor.calculateVisibleRange()
return ActionUtil.underModalProgress(project, "") { InlayHintsPass(myFixture.file, collectors, myFixture.editor, visibleRange, sharedSink) }
}
private fun InlayHintsPass.collectAndApply() {

View File

@@ -3,6 +3,7 @@ package com.intellij.codeInsight.hints.declarative.impl
import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator
import com.intellij.codeInsight.hints.declarative.*
import com.intellij.openapi.actionSystem.ex.ActionUtil
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.Inlay
import com.intellij.psi.PsiElement
@@ -30,7 +31,7 @@ class DeclarativeInlayHintsPassTest : LightPlatformCodeInsightFixture4TestCase()
}
}
}, "test.inlay.provider", emptyMap())
val pass = DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(passInfo), false)
val pass = createPass(passInfo, false)
collectAndApplyPass(pass)
@@ -53,12 +54,12 @@ class DeclarativeInlayHintsPassTest : LightPlatformCodeInsightFixture4TestCase()
}
}
collectAndApplyPass(DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(providerInfo), false))
collectAndApplyPass(createPass(providerInfo, false))
assertEquals(listOf(TextInlayPresentationEntry("inlay text", clickArea = null)), getInlays().single().getEntries())
assertNull(provider.hintAdder) // make sure no inlay is added on the next pass
collectAndApplyPass(DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(providerInfo), false))
collectAndApplyPass(createPass(providerInfo, false))
assertEquals(emptyList<Any>(), getInlays())
}
@@ -73,7 +74,7 @@ class DeclarativeInlayHintsPassTest : LightPlatformCodeInsightFixture4TestCase()
}
}
collectAndApplyPass(DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(providerInfo), false))
collectAndApplyPass(createPass(providerInfo, false))
val inlay = getInlays().single()
assertEquals(listOf(TextInlayPresentationEntry("inlay text", clickArea = null)), inlay.getEntries())
@@ -83,7 +84,7 @@ class DeclarativeInlayHintsPassTest : LightPlatformCodeInsightFixture4TestCase()
}
}
collectAndApplyPass(DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(providerInfo), false))
collectAndApplyPass(createPass(providerInfo, false))
val newInlay = getInlays().single()
TestCase.assertSame(inlay, newInlay)
assertEquals(listOf(TextInlayPresentationEntry("new text", clickArea = null)), newInlay.getEntries())
@@ -109,7 +110,7 @@ class DeclarativeInlayHintsPassTest : LightPlatformCodeInsightFixture4TestCase()
}
}
collectAndApplyPass(DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(providerInfo), false))
collectAndApplyPass(createPass(providerInfo, false))
val entries = getInlays().map { it.getEntries().single() }
assertEquals(listOf(
@@ -120,6 +121,12 @@ class DeclarativeInlayHintsPassTest : LightPlatformCodeInsightFixture4TestCase()
), entries)
}
private fun createPass(providerInfo: InlayProviderPassInfo, isProviderDisabled: Boolean=false): DeclarativeInlayHintsPass {
return ActionUtil.underModalProgress(project, "") {
DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(providerInfo), isProviderDisabled, isProviderDisabled)
}
}
@Test
fun testUpdateEnabled() {
myFixture.configureByText("test.txt", "my content of file")
@@ -131,14 +138,14 @@ class DeclarativeInlayHintsPassTest : LightPlatformCodeInsightFixture4TestCase()
}
}
collectAndApplyPass(DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(providerInfo), false, false))
collectAndApplyPass(createPass(providerInfo, false))
assertFalse(getInlays().single().renderer.presentationList.isDisabled)
provider.hintAdder = {
addPresentation(InlineInlayPosition(2, true, priority = 1), hasBackground = true) {
text("1")
}
}
collectAndApplyPass(DeclarativeInlayHintsPass(myFixture.file, myFixture.editor, listOf(providerInfo), false, true))
collectAndApplyPass(createPass(providerInfo, true))
assertTrue(getInlays().single().renderer.presentationList.isDisabled)
}

View File

@@ -3,6 +3,7 @@ package com.intellij.openapi.editor;
import com.intellij.codeInsight.daemon.impl.IndentsPass;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.event.DocumentEvent;
@@ -300,7 +301,7 @@ public class EditorPaintingTest extends EditorPaintingTestCase {
}
private void runIndentsPass() {
IndentsPass indentsPass = new IndentsPass(getProject(), getEditor(), getFile());
IndentsPass indentsPass = ActionUtil.underModalProgress(getProject(), "", ()->new IndentsPass(getProject(), getEditor(), getFile()));
indentsPass.doCollectInformation(new EmptyProgressIndicator());
indentsPass.doApplyInformationToEditor();
}

View File

@@ -31,7 +31,10 @@ abstract class DeclarativeInlayHintsProviderTestCase : BasePlatformTestCase() {
val file = myFixture.file!!
val editor = myFixture.editor
val providerInfo = InlayProviderPassInfo(provider, "provider.id", enabledOptions)
val pass = DeclarativeInlayHintsPass(file, editor, listOf(providerInfo), isPreview = false)
val pass = ActionUtil.underModalProgress(project, "") {
DeclarativeInlayHintsPass(file, editor, listOf(providerInfo), isPreview = false)
}
applyPassAndCheckResult(pass, expectedFile, sourceText, expectedText)
}
@@ -40,8 +43,9 @@ abstract class DeclarativeInlayHintsProviderTestCase : BasePlatformTestCase() {
val fileName = "preview." + (language.associatedFileType?.defaultExtension ?: error("language must have extension"))
myFixture.configureByText(fileName, InlayDumpUtil.removeHints(previewText))
val pass = DeclarativeInlayHintsPassFactory.createPassForPreview(myFixture.file, myFixture.editor, provider, providerId,
emptyMap(), false)
val pass = ActionUtil.underModalProgress(project, "") {
DeclarativeInlayHintsPassFactory.createPassForPreview(myFixture.file, myFixture.editor, provider, providerId, emptyMap(), false)
}
applyPassAndCheckResult(pass, null, previewText, expectedText)
}