diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/stickyLines/StickyLinesCollector.kt b/platform/platform-impl/src/com/intellij/openapi/editor/impl/stickyLines/StickyLinesCollector.kt index 8a59622c3184..dab4a543d50e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/stickyLines/StickyLinesCollector.kt +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/stickyLines/StickyLinesCollector.kt @@ -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 = findOutdatedLines(stickyModel, linesToAdd, removeExisting) // mutates linesToAdd + val outdatedLines: List = 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 { + val toRemove: MutableList = mutableListOf() + stickyModel.processStickyLines(null) { existingLine: StickyLine -> + toRemove.add(existingLine) + true + } + return toRemove + } + + private fun mergeWithExistingLines( stickyModel: StickyLinesModel, linesToAdd: MutableSet, - removeExisting: Boolean, ): List { val outdatedLines: MutableList = 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 } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/stickyLines/StickyLinesModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/stickyLines/StickyLinesModel.java index 13154b75b29f..69d7d6073ac4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/stickyLines/StickyLinesModel.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/stickyLines/StickyLinesModel.java @@ -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 processor) { - processStickyLines(endOffset, null, processor); + processStickyLines(null, endOffset, processor); } void processStickyLines(@Nullable String source, @NotNull Processor processor) { - processStickyLines(myMarkupModel.getDocument().getTextLength(), source, processor); + processStickyLines(source, myMarkupModel.getDocument().getTextLength(), processor); } - void processStickyLines(int endOffset, @Nullable String source, @NotNull Processor processor) { + private void processStickyLines(@Nullable String source, int endOffset, @NotNull Processor 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 {