IJPL-449 Sticky lines: fix for issue with burning zombies

GitOrigin-RevId: bf798e6bd431248047c22957daf16edcbbee2741
This commit is contained in:
Aleksandr Trushev
2024-01-31 15:50:16 +01:00
committed by intellij-monorepo-bot
parent 67fee31911
commit d661462cc4
2 changed files with 27 additions and 23 deletions

View File

@@ -47,33 +47,39 @@ class StickyLinesCollector(private val project: Project, private val document: D
// markup model could contain raised zombies on the first pass.
// we should burn them all here, otherwise an empty panel will appear
val removeExisting: Boolean = stickyModel.isFirstUpdate()
val outdatedLines: List<StickyLine> = findOutdatedLines(stickyModel, linesToAdd, removeExisting) // mutates linesToAdd
val outdatedLines: List<StickyLine> = if (removeExisting) {
removeExistingLines(stickyModel)
} else {
mergeWithExistingLines(stickyModel, linesToAdd) // mutates linesToAdd
}
for (toRemove: StickyLine in outdatedLines) {
stickyModel.removeStickyLine(toRemove)
}
for (toAdd: StickyLineInfo in linesToAdd) {
stickyModel.addStickyLine(toAdd.textOffset, toAdd.endOffset, STICKY_LINE_SOURCE, toAdd.debugText)
stickyModel.addStickyLine(STICKY_LINE_SOURCE, toAdd.textOffset, toAdd.endOffset, toAdd.debugText)
}
stickyModel.notifyListeners()
}
private fun findOutdatedLines(
private fun removeExistingLines(stickyModel: StickyLinesModel): List<StickyLine> {
val toRemove: MutableList<StickyLine> = mutableListOf()
stickyModel.processStickyLines(null) { existingLine: StickyLine ->
toRemove.add(existingLine)
true
}
return toRemove
}
private fun mergeWithExistingLines(
stickyModel: StickyLinesModel,
linesToAdd: MutableSet<StickyLineInfo>,
removeExisting: Boolean,
): List<StickyLine> {
val outdatedLines: MutableList<StickyLine> = mutableListOf()
stickyModel.processStickyLines(STICKY_LINE_SOURCE) { existingLine: StickyLine ->
if (removeExisting) {
// remove all existing
val existing = StickyLineInfo(existingLine.textRange())
val keepExisting = linesToAdd.remove(existing)
if (!keepExisting) {
outdatedLines.add(existingLine)
} else {
// merge with existing
val existing = StickyLineInfo(existingLine.textRange())
val keepExisting = linesToAdd.remove(existing)
if (!keepExisting) {
outdatedLines.add(existingLine)
}
}
true
}

View File

@@ -14,7 +14,6 @@ import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.Strings;
import com.intellij.util.Processor;
import com.intellij.util.concurrency.annotations.RequiresEdt;
import org.jetbrains.annotations.NotNull;
@@ -70,7 +69,7 @@ public final class StickyLinesModel {
return isFirstTime;
}
public StickyLine addStickyLine(int textOffset, int endOffset, @NotNull String source, @Nullable String debugText) {
public @NotNull StickyLine addStickyLine(@NotNull String source, int textOffset, int endOffset, @Nullable String debugText) {
if (textOffset >= endOffset) {
throw new IllegalArgumentException(String.format(
"sticky line endOffset %s should be less than textOffset %s", textOffset, endOffset
@@ -95,14 +94,14 @@ public final class StickyLinesModel {
}
void processStickyLines(int endOffset, @NotNull Processor<? super StickyLine> processor) {
processStickyLines(endOffset, null, processor);
processStickyLines(null, endOffset, processor);
}
void processStickyLines(@Nullable String source, @NotNull Processor<? super StickyLine> processor) {
processStickyLines(myMarkupModel.getDocument().getTextLength(), source, processor);
processStickyLines(source, myMarkupModel.getDocument().getTextLength(), processor);
}
void processStickyLines(int endOffset, @Nullable String source, @NotNull Processor<? super StickyLine> processor) {
private void processStickyLines(@Nullable String source, int endOffset, @NotNull Processor<? super StickyLine> processor) {
myMarkupModel.processRangeHighlightersOverlappingWith(
0,
endOffset,
@@ -110,7 +109,8 @@ public final class StickyLinesModel {
if (STICKY_LINE_ATTRIBUTE.equals(highlighter.getTextAttributesKey()) && isSuitableSource(highlighter, source)) {
StickyLineImpl stickyLine = highlighter.getUserData(STICKY_LINE_IMPL_KEY);
if (stickyLine == null) {
stickyLine = new StickyLineImpl(highlighter.getDocument(), highlighter, null);
// probably it is a zombie highlighter
stickyLine = new StickyLineImpl(highlighter.getDocument(), highlighter, "StickyZombie");
}
return processor.process(stickyLine);
} else {
@@ -120,10 +120,8 @@ public final class StickyLinesModel {
);
}
private static Boolean isSuitableSource(RangeHighlighterEx highlighter, @Nullable String source){
if (source == null) return true;
return Strings.areSameInstance(highlighter.getUserData(STICKY_LINE_SOURCE), source);
private static boolean isSuitableSource(RangeHighlighterEx highlighter, @Nullable String source) {
return source == null || source.equals(highlighter.getUserData(STICKY_LINE_SOURCE));
}
interface Listener {