correctly dispose invisible whole-file range highlighters to fix IJPL-17382 "Configure interpreter" problem for any language is duplicated

GitOrigin-RevId: 46cfe186c48817e2502af8a61e8a9131f639a2dd
This commit is contained in:
Alexey Kudravtsev
2024-05-01 14:39:38 +02:00
committed by intellij-monorepo-bot
parent 09411b5557
commit 35e659d314
3 changed files with 53 additions and 13 deletions

View File

@@ -28,6 +28,7 @@ import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.fileTypes.PlainTextFileType;
@@ -636,7 +637,7 @@ public class DaemonInspectionsRespondToChangesTest extends DaemonAnalyzerTestCas
assertNull(expectedVisibleRange); // check the inspection was run
}
// add file-level "blah" if there are identifiers containing "XXX"
// add file-level "blah" for each identifier containing "XXX"
private static class MyFileLevelInspection extends MyInspectionBase {
@NotNull
@Override
@@ -670,6 +671,40 @@ public class DaemonInspectionsRespondToChangesTest extends DaemonAnalyzerTestCas
assertOneElement(myDaemonCodeAnalyzer.getFileLevelHighlights(getProject(), getFile()));
}
public void testFileLevelHighlightingDoesNotDuplicateOnTypingOrOnFileCloseReopen() {
registerInspection(new MyFileLevelInspection());
@Language("JAVA")
String text = """
class X {
int XXX<caret>;
}""";
PsiFile psiFile = configureByText(JavaFileType.INSTANCE, text);
assertEmpty(highlightErrors());
assertOneElement(myDaemonCodeAnalyzer.getFileLevelHighlights(getProject(), getFile()));
FileEditorManager.getInstance(myProject).closeFile(psiFile.getVirtualFile());
for (int i=0; i<100; i++) {
configureByExistingFile(psiFile.getVirtualFile());
getEditor().getCaretModel().moveToOffset(getEditor().getDocument().getText().indexOf("XXX") + "XXX".length());
UIUtil.dispatchAllInvocationEvents();
type('2');
assertEmpty(highlightErrors());
UIUtil.dispatchAllInvocationEvents();
assertOneElement(myDaemonCodeAnalyzer.getFileLevelHighlights(getProject(), getFile()));
UIUtil.dispatchAllInvocationEvents();
backspace();
assertEmpty(highlightErrors());
UIUtil.dispatchAllInvocationEvents();
assertOneElement(myDaemonCodeAnalyzer.getFileLevelHighlights(getProject(), getFile()));
LOG.debug("i = " + i);
FileEditorManager.getInstance(myProject).closeFile(psiFile.getVirtualFile());
}
}
public void testFileLevelWithEverChangingDescriptionMustUpdateOnTyping() {
// add file-level "blah" if there are identifiers containing "xxx"
class XXXIdentifierFileLevelInspection extends MyInspectionBase {

View File

@@ -244,10 +244,10 @@ final class HighlightInfoUpdaterImpl extends HighlightInfoUpdater implements Dis
}
// disposes highlighter, and schedules removal from the file-level component if this highlighter happened to be file-level
private static void disposeWithFileLevel(@NotNull HighlightInfo info,
@NotNull RangeHighlighterEx highlighter,
@NotNull HighlightingSession highlightingSession) {
if (info.isFileLevelAnnotation()) {
static void disposeWithFileLevel(@Nullable HighlightInfo info,
@NotNull RangeHighlighterEx highlighter,
@NotNull HighlightingSession highlightingSession) {
if (info != null && info.isFileLevelAnnotation()) {
((HighlightingSessionImpl)highlightingSession).removeFileLevelHighlight(info);
}
highlighter.dispose();
@@ -357,7 +357,7 @@ final class HighlightInfoUpdaterImpl extends HighlightInfoUpdater implements Dis
RangeHighlighterEx salvagedHighlighter = toReuse.pickupHighlighterFromGarbageBin(0, psiFile.getTextLength(), -409423948);
HighlightInfo oldFileInfo = salvagedHighlighter == null ? null : HighlightInfo.fromRangeHighlighter(salvagedHighlighter);
if (oldFileInfo != null) {
((HighlightingSessionImpl)session).removeFileLevelHighlight(oldFileInfo);
disposeWithFileLevel(oldFileInfo, salvagedHighlighter, session);
salvagedHighlighter = null;
}
((HighlightingSessionImpl)session).addFileLevelHighlight(info, salvagedHighlighter);

View File

@@ -231,16 +231,13 @@ public final class UpdateHighlightersUtil {
// do not remove obsolete highlighters if we are in "essential highlighting only" mode, because otherwise all inspection-produced results would be gone
for (RangeHighlighter highlighter : infosToRemove.forAllInGarbageBin()) {
boolean shouldRemove = shouldRemoveHighlighter(highlighter, session);
HighlightInfo info = HighlightInfo.fromRangeHighlighter(highlighter);
if (LOG.isDebugEnabled()) {
LOG.debug("incinerateObsoleteHighlighters "+highlighter+"; shouldRemove:"+shouldRemove);
}
if (shouldRemove) {
highlighter.dispose();
HighlightInfo info = HighlightInfo.fromRangeHighlighter(highlighter);
HighlightInfoUpdaterImpl.disposeWithFileLevel(info, (RangeHighlighterEx)highlighter, session);
changed = true;
if (info != null && info.isFileLevelAnnotation()) {
((HighlightingSessionImpl)session).removeFileLevelHighlight(info);
}
}
}
return changed;
@@ -458,8 +455,16 @@ public final class UpdateHighlightersUtil {
});
for (HighlightInfo info : toRemove) {
if (!info.getHighlighter().isValid() || info.type.equals(HighlightInfoType.WRONG_REF)) {
info.getHighlighter().dispose();
RangeHighlighterEx highlighter = info.getHighlighter();
if (!highlighter.isValid() || info.type.equals(HighlightInfoType.WRONG_REF)) {
if (info.isFileLevelAnnotation()) {
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(project);
PsiFile psiFile = PsiDocumentManager.getInstance(project).getCachedPsiFile(document);
if (psiFile != null) {
codeAnalyzer.removeFileLevelHighlight(psiFile, info);
}
}
highlighter.dispose();
}
}