RUST-19514 fix unsynchronized context installation on file level annotations

(cherry picked from commit 8d24914155332f0ed5eb63814686e26da5d307aa)

IJ-CR-192608

GitOrigin-RevId: 19e52e7bd8fde57b215b2a2c9abb70b2ad99c415
This commit is contained in:
Max Medvedev
2026-02-19 16:51:49 +01:00
committed by intellij-monorepo-bot
parent 70d730eab9
commit 198edd9e72
3 changed files with 53 additions and 8 deletions

View File

@@ -1,11 +1,19 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.lang.LanguageAnnotators
import com.intellij.lang.LanguageExtensionPoint
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.Annotator
import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.application.readAction
import com.intellij.openapi.editor.ex.EditorMarkupModel
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.util.application
import kotlinx.coroutines.runBlocking
import org.intellij.lang.annotations.Language
@@ -41,11 +49,42 @@ class TrafficLightTest : DaemonAnalyzerTestCase() {
)
}
fun `test error counter after adding and removing file level annotation`() {
class AnnotatorRegisteringFileLevelErrorIfEmptyFile : Annotator {
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
if (element is PsiFile && element.textLength == 0) {
holder.newAnnotation(HighlightSeverity.ERROR, "Empty file").fileLevel().create()
}
}
}
val annotator = AnnotatorRegisteringFileLevelErrorIfEmptyFile()
val keyedLazyInstance = LanguageExtensionPoint<Annotator>("JAVA", annotator.javaClass.name, PluginManagerCore.getPlugin(PluginManagerCore.CORE_ID)!!)
LanguageAnnotators.EP_NAME.point.registerExtension(keyedLazyInstance, testRootDisposable)
doTrafficRendererTest(
listOf(
"class Main {}", // no error
"", // file level error is added by AnnotatorRegisteringFileLevelErrorIfEmptyFile
"class Main {}" // no error again
),
listOf(HighlightSeverity.ERROR to 0),
)
}
private fun doTrafficRendererTest(
@Language("JAVA") text: String,
vararg expectedSeverities: SeverityValue,
) {
configureByText(JavaFileType.INSTANCE, text)
doTrafficRendererTest(listOf(text), listOf(*expectedSeverities))
}
private fun doTrafficRendererTest(
fileTextSnapshots: List<String>,
expectedSeverities: List<SeverityValue>,
) {
require(fileTextSnapshots.isNotEmpty())
configureByText(JavaFileType.INSTANCE, fileTextSnapshots.first())
val editorMarkupModel = editor.markupModel as EditorMarkupModel
@@ -53,6 +92,13 @@ class TrafficLightTest : DaemonAnalyzerTestCase() {
doHighlighting()
fileTextSnapshots.drop(1).forEach {
application.runWriteAction {
editor.document.setText(it)
}
doHighlighting()
}
val trafficLightRenderer = editorMarkupModel.errorStripeRenderer as TrafficLightRenderer
val status = runBlocking {
readAction {

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeInsight.multiverse.CodeInsightContext;
@@ -1516,11 +1516,13 @@ public final class HighlightInfoUpdaterImpl extends HighlightInfoUpdater impleme
if (toReuse != null && toReuse.isValid()) {
highlighter = toReuse;
BackgroundUpdateHighlightersUtil.associateInfoAndHighlighter(info, highlighter);
CodeInsightContextHighlightingUtil.installCodeInsightContext(highlighter, project, context);
}
else {
highlighter = markupModel.addRangeHighlighterAndChangeAttributes(null, 0, document.getTextLength(), FILE_LEVEL_FAKE_LAYER,
HighlighterTargetArea.EXACT_RANGE, false, ex -> {
BackgroundUpdateHighlightersUtil.associateInfoAndHighlighter(info, ex);
CodeInsightContextHighlightingUtil.installCodeInsightContext(ex, project, context);
});
}
highlighter.setGreedyToLeft(true);
@@ -1529,9 +1531,6 @@ public final class HighlightInfoUpdaterImpl extends HighlightInfoUpdater impleme
// create a fake whole-file highlighter which will track the document size changes
// and which will make possible to calculate correct `info.getActualEndOffset()`
info.setGroup(group);
if (context != null) {
CodeInsightContextHighlightingUtil.installCodeInsightContext(highlighter, project, context);
}
return highlighter;
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:ApiStatus.Experimental
@file:JvmName("CodeInsightContextHighlightingUtil")
@@ -10,7 +10,7 @@ import com.intellij.openapi.util.Key
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Experimental
fun RangeHighlighter.installCodeInsightContext(project: Project, context: CodeInsightContext) {
fun RangeHighlighter.installCodeInsightContext(project: Project, context: CodeInsightContext?) {
if (isSharedSourceSupportEnabled(project)) {
putUserData(highlighterContextKey, context)
}