From d09796e265325024f1371fd43543cd1de7be6d20 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 26 Jul 2022 11:23:17 +0200 Subject: [PATCH] lst: recover from catastrophic tracker refresh failure Improve debug logging for "EA-259651 IOOBE: DiffUtil.getLines" GitOrigin-RevId: 927cae250ee974d91bc34f9eb149ec72b35f9f92 --- .../openapi/editor/impl/DocumentImpl.java | 6 ++- .../openapi/vcs/ex/DocumentTracker.kt | 42 ++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index 0346cb8ebd75..df48cc6cc8ff 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -1202,7 +1202,11 @@ public final class DocumentImpl extends UserDataHolderBase implements DocumentEx @Override public String toString() { - return "DocumentImpl[" + FileDocumentManager.getInstance().getFile(this) + (isInEventsHandling() ? ",inEventHandling" : "") + "]"; + return "DocumentImpl[" + FileDocumentManager.getInstance().getFile(this) + + (isInEventsHandling() ? ",inEventHandling" : "") + + (!myAssertThreading ? ",nonWriteThreadOnly" : "") + + (myAcceptSlashR ? ",acceptSlashR" : "") + + "]"; } @NotNull diff --git a/platform/diff-impl/src/com/intellij/openapi/vcs/ex/DocumentTracker.kt b/platform/diff-impl/src/com/intellij/openapi/vcs/ex/DocumentTracker.kt index 808818271a3b..6e3ae5115620 100644 --- a/platform/diff-impl/src/com/intellij/openapi/vcs/ex/DocumentTracker.kt +++ b/platform/diff-impl/src/com/intellij/openapi/vcs/ex/DocumentTracker.kt @@ -13,15 +13,18 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationListener import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.event.DocumentEvent import com.intellij.openapi.editor.event.DocumentListener +import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vcs.ex.DocumentTracker.Block import com.intellij.openapi.vcs.ex.DocumentTracker.Handler import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.containers.PeekableIteratorWrapper import org.jetbrains.annotations.ApiStatus +import java.util.* import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock import kotlin.math.max @@ -174,11 +177,25 @@ class DocumentTracker( return } - tracker.refreshDirty(document1.immutableCharSequence, - document2.immutableCharSequence, - document1.lineOffsets, - document2.lineOffsets, - fastRefresh) + try { + tracker.refreshDirty(document1.immutableCharSequence, + document2.immutableCharSequence, + document1.lineOffsets, + document2.lineOffsets, + fastRefresh) + } + catch (e: ProcessCanceledException) { + throw e + } + catch (e: Throwable) { + logger().error( + "document1: $document1, document2: $document2, " + + "isFrozen1: ${freezeHelper.isFrozen(Side.LEFT)}, isFrozen2: ${freezeHelper.isFrozen(Side.RIGHT)}, " + + "isBulk1: ${document1.isInBulkUpdate}, isBulk2: ${document2.isInBulkUpdate}", + e) + + tracker.resetTrackerState(DiffUtil.getLineCount(document1), DiffUtil.getLineCount(document2)) + } } } @@ -583,6 +600,21 @@ private class LineTracker(private val handlers: List, afterBulkRangeChange(isDirty) } + /** + * Reset to the simplest valid state. Hopefully, the next full refresh will be successful. + */ + fun resetTrackerState(lineCount1: Int, lineCount2: Int) { + val fullRange = Range(0, lineCount1, 0, lineCount2) + val dirtyBlock = Block(fullRange, true, false) + onRangesChanged(emptyList(), dirtyBlock) + + blocks = listOf(dirtyBlock) + isDirty = true + forceMergeNearbyBlocks = false + + afterBulkRangeChange(isDirty) + } + fun rangeChanged(side: Side, startLine: Int, beforeLength: Int, afterLength: Int) { val data = RangeChangeHandler().run(blocks, side, startLine, beforeLength, afterLength)