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 6ad73f73f889..9ec56d6ced52 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 @@ -1182,15 +1182,15 @@ public final class DocumentImpl extends UserDataHolderBase implements DocumentEx } @NotNull - String dumpState() { + public String dumpState() { @NonNls StringBuilder result = new StringBuilder(); - result.append(", intervals:\n"); - for (int line = 0; line < getLineCount(); line++) { - result.append(line).append(": ").append(getLineStartOffset(line)).append("-") - .append(getLineEndOffset(line)).append(", "); + result.append("intervals:\n"); + int lineCount = getLineCount(); + for (int line = 0; line < lineCount; line++) { + result.append(line).append(": ").append(getLineStartOffset(line)).append("-").append(getLineEndOffset(line)).append(", "); } - if (result.length() > 0) { - result.setLength(result.length() - 1); + if (lineCount > 0) { + result.setLength(result.length() - 2); } return result.toString(); } diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java index 11ac1839c021..5e762a32e371 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java @@ -1452,4 +1452,13 @@ abstract class IntervalTreeImpl extends RedBlackTree implements IntervalTr l.readLock().unlock(); } } + + String dumpState() { + StringBuilder b = new StringBuilder("[\n"); + processAll(i -> { + b.append(' ').append(i).append('\n'); + return true; + }); + return b.append("]").toString(); + } } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java index 1cf32d94fb26..e6bd9f2a6e12 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java @@ -49,7 +49,9 @@ final class PersistentRangeHighlighterImpl extends RangeHighlighterImpl { public String toString() { return "PersistentRangeHighlighter" + (isGreedyToLeft() ? "[" : "(") + - (isValid() ? "valid" : "invalid") + "," + getStartOffset() + "," + getEndOffset() + + (isValid() ? "valid" : "invalid") + "," + + (getTargetArea() == HighlighterTargetArea.LINES_IN_RANGE ? "whole-line" : "exact") + "," + + getStartOffset() + "," + getEndOffset() + (isGreedyToRight() ? "]" : ")"); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ErrorStripeMarkerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ErrorStripeMarkerImpl.java index c14263a58a2d..1a718f2300eb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ErrorStripeMarkerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ErrorStripeMarkerImpl.java @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.editor.impl; +import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.ex.DocumentEx; @@ -25,6 +26,9 @@ class ErrorStripeMarkerImpl extends RangeMarkerImpl { @Override protected void changedUpdateImpl(@NotNull DocumentEvent e) { + int oldStart = intervalStart(); + int oldEnd = intervalEnd(); + if (myHighlighter.isPersistent()) { persistentHighlighterUpdate(e, myHighlighter.getTargetArea() == HighlighterTargetArea.LINES_IN_RANGE); } @@ -32,23 +36,44 @@ class ErrorStripeMarkerImpl extends RangeMarkerImpl { super.changedUpdateImpl(e); } - validateState(e); + validateState(e, oldStart, oldEnd); } - private void validateState(DocumentEvent e) { + private void validateState(DocumentEvent e, int oldStart, int oldEnd) { if (myHighlighter.isValid()) { if (!isValid()) { - LOG.error("Base highlighter " + myHighlighter + " is valid, mirror " + this + " is invalid after " + e); + reportError("Base highlighter " + myHighlighter + " is valid, mirror " + + this + "(prev state: " + oldStart + "-" + oldEnd + ") is invalid after " + e); } else if (intervalStart() != myHighlighter.getStartOffset() || intervalEnd() != myHighlighter.getEndOffset()) { - LOG.error("Mirror highlighter " + this + " diverged from base one " + myHighlighter + " after " + e); + reportError("Mirror highlighter " + this + "(prev state: " + oldStart + "-" + oldEnd + + ") diverged from base one " + myHighlighter + " after " + e); setIntervalStart(myHighlighter.getStartOffset()); setIntervalEnd(myHighlighter.getEndOffset()); } } else if (isValid()) { - LOG.error("Base highlighter " + myHighlighter + " is invalid, mirror " + this + " is valid after " + e); + reportError("Base highlighter " + myHighlighter + " is invalid, mirror " + this + "(prev state: " + oldStart + "-" + oldEnd + + ") is valid after " + e); invalidate(e); } } + + private void reportError(String message) { + DocumentEx document = getDocument(); + LOG.error(message, + new Attachment("document.txt", document instanceof DocumentImpl ? ((DocumentImpl)document).dumpState() : "" ), + new Attachment("originalTree.txt", myHighlighter instanceof RangeHighlighterImpl ? + ((RangeHighlighterImpl)myHighlighter).myNode.getTree().dumpState() : ""), + new Attachment("mirrorTree.txt", myNode.getTree().dumpState())); + } + + @Override + public String toString() { + String result = super.toString(); + if (myNode.isFlagSet(RangeHighlighterTree.RHNode.IS_PERSISTENT)) { + result += "(persistent)"; + } + return result; + } }