diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/ManualRangeMarker.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/ManualRangeMarker.java index ac40c1190d8a..cccd00c6de65 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/ManualRangeMarker.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/ManualRangeMarker.java @@ -19,7 +19,8 @@ import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; import com.intellij.openapi.editor.impl.event.RetargetRangeMarkers; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.ProperTextRange; +import com.intellij.openapi.util.Segment; +import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,19 +28,21 @@ import org.jetbrains.annotations.Nullable; * A range marker that has to be manually updated with {@link #getUpdatedRange(DocumentEvent, FrozenDocument)}. * Can hold PSI-based range and be updated when the document is committed. */ -public class ManualRangeMarker { - private final ProperTextRange myRange; +public class ManualRangeMarker implements Segment { + private final int myStart; + private final int myEnd; private final boolean myGreedyLeft; private final boolean myGreedyRight; private final boolean mySurviveOnExternalChange; private final PersistentRangeMarker.LinesCols myLinesCols; - public ManualRangeMarker(@NotNull ProperTextRange range, + public ManualRangeMarker(int start, int end, boolean greedyLeft, boolean greedyRight, boolean surviveOnExternalChange, @Nullable PersistentRangeMarker.LinesCols linesCols) { - myRange = range; + myStart = start; + myEnd = end; myGreedyLeft = greedyLeft; myGreedyRight = greedyRight; mySurviveOnExternalChange = surviveOnExternalChange; @@ -50,34 +53,39 @@ public class ManualRangeMarker { public ManualRangeMarker getUpdatedRange(@NotNull DocumentEvent event, @NotNull FrozenDocument documentBefore) { if (event instanceof RetargetRangeMarkers) { int start = ((RetargetRangeMarkers)event).getStartOffset(); - if (myRange.getStartOffset() >= start && myRange.getEndOffset() <= ((RetargetRangeMarkers)event).getEndOffset()) { - ProperTextRange range = myRange.shiftRight(((RetargetRangeMarkers)event).getMoveDestinationOffset() - start); - return new ManualRangeMarker(range, myGreedyLeft, myGreedyRight, mySurviveOnExternalChange, null); + if (myStart >= start && myEnd <= ((RetargetRangeMarkers)event).getEndOffset()) { + int delta = ((RetargetRangeMarkers)event).getMoveDestinationOffset() - start; + return new ManualRangeMarker(myStart + delta, myEnd + delta, myGreedyLeft, myGreedyRight, mySurviveOnExternalChange, null); } } - if (mySurviveOnExternalChange && PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, myRange)) { + if (mySurviveOnExternalChange && PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, myStart, myEnd)) { PersistentRangeMarker.LinesCols linesCols = myLinesCols != null ? myLinesCols - : PersistentRangeMarker.storeLinesAndCols(myRange, documentBefore); - Pair pair = + : PersistentRangeMarker.storeLinesAndCols(documentBefore, myStart, myEnd); + Pair pair = linesCols == null ? null : PersistentRangeMarker.translateViaDiff((DocumentEventImpl)event, linesCols); if (pair != null) { - return new ManualRangeMarker(pair.first, myGreedyLeft, myGreedyRight, true, pair.second); + return new ManualRangeMarker(pair.first.getStartOffset(), pair.first.getEndOffset(), myGreedyLeft, myGreedyRight, true, pair.second); } } - ProperTextRange range = RangeMarkerImpl.applyChange(event, myRange.getStartOffset(), myRange.getEndOffset(), myGreedyLeft, myGreedyRight); - return range == null ? null : new ManualRangeMarker(range, myGreedyLeft, myGreedyRight, mySurviveOnExternalChange, null); + TextRange range = RangeMarkerImpl.applyChange(event, myStart, myEnd, myGreedyLeft, myGreedyRight); + return range == null ? null : new ManualRangeMarker(range.getStartOffset(), range.getEndOffset(), myGreedyLeft, myGreedyRight, mySurviveOnExternalChange, null); } - @NotNull - public ProperTextRange getRange() { - return myRange; + @Override + public int getStartOffset() { + return myStart; + } + + @Override + public int getEndOffset() { + return myEnd; } @Override public String toString() { - return "ManualRangeMarker" + myRange; + return "ManualRangeMarker" + TextRange.create(this); } } diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarker.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarker.java index 3fc8bb200653..20946c4c4ed3 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarker.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarker.java @@ -20,8 +20,8 @@ import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.ProperTextRange; import com.intellij.openapi.util.Segment; +import com.intellij.openapi.util.TextRange; import com.intellij.util.ObjectUtils; import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; @@ -41,18 +41,17 @@ class PersistentRangeMarker extends RangeMarkerImpl { PersistentRangeMarker(DocumentEx document, int startOffset, int endOffset, boolean register) { super(document, startOffset, endOffset, register); - myLinesCols = ObjectUtils.assertNotNull(storeLinesAndCols(this, document)); + myLinesCols = ObjectUtils.assertNotNull(storeLinesAndCols(document, getStartOffset(), getEndOffset())); } @Nullable - static LinesCols storeLinesAndCols(Segment range, Document myDocument) { + static LinesCols storeLinesAndCols(Document myDocument, int startOffset, int endOffset) { int myStartLine; int myStartColumn; int myEndLine; int myEndColumn; // document might have been changed already - int startOffset = range.getStartOffset(); if (startOffset <= myDocument.getTextLength()) { myStartLine = myDocument.getLineNumber(startOffset); myStartColumn = startOffset - myDocument.getLineStartOffset(myStartLine); @@ -63,7 +62,6 @@ class PersistentRangeMarker extends RangeMarkerImpl { else { return null; } - int endOffset = range.getEndOffset(); if (endOffset <= myDocument.getTextLength()) { myEndLine = myDocument.getLineNumber(endOffset); myEndColumn = endOffset - myDocument.getLineStartOffset(myEndLine); @@ -79,7 +77,7 @@ class PersistentRangeMarker extends RangeMarkerImpl { } @Nullable - static Pair translateViaDiff(@NotNull final DocumentEventImpl event, @NotNull LinesCols linesCols) { + static Pair translateViaDiff(@NotNull final DocumentEventImpl event, @NotNull LinesCols linesCols) { try { int myStartLine = event.translateLineViaDiffStrict(linesCols.myStartLine); Document document = event.getDocument(); @@ -105,7 +103,7 @@ class PersistentRangeMarker extends RangeMarkerImpl { return null; } - return Pair.create(new ProperTextRange(start, end), new LinesCols(myStartLine, linesCols.myStartColumn, myEndLine, linesCols.myEndColumn)); + return Pair.create(new TextRange(start, end), new LinesCols(myStartLine, linesCols.myStartColumn, myEndLine, linesCols.myEndColumn)); } catch (FilesTooBigForDiffException e) { return null; @@ -116,7 +114,7 @@ class PersistentRangeMarker extends RangeMarkerImpl { protected void changedUpdateImpl(@NotNull DocumentEvent e) { if (!isValid()) return; - Pair pair = + Pair pair = applyChange(e, this, intervalStart(), intervalEnd(), isGreedyToLeft(), isGreedyToRight(), myLinesCols); if (pair == null) { invalidate(e); @@ -129,17 +127,17 @@ class PersistentRangeMarker extends RangeMarkerImpl { } @Nullable - private static Pair applyChange(DocumentEvent event, Segment range, int intervalStart, int intervalEnd, boolean greedyLeft, boolean greedyRight, LinesCols linesCols) { - final boolean shouldTranslateViaDiff = PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, range); - Pair translated = null; + private static Pair applyChange(DocumentEvent event, Segment range, int intervalStart, int intervalEnd, boolean greedyLeft, boolean greedyRight, LinesCols linesCols) { + final boolean shouldTranslateViaDiff = PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, range.getStartOffset(), range.getEndOffset()); + Pair translated = null; if (shouldTranslateViaDiff) { translated = translateViaDiff((DocumentEventImpl)event, linesCols); } if (translated == null) { - ProperTextRange fallback = applyChange(event, intervalStart, intervalEnd, greedyLeft, greedyRight); + TextRange fallback = applyChange(event, intervalStart, intervalEnd, greedyLeft, greedyRight); if (fallback == null) return null; - LinesCols lc = storeLinesAndCols(fallback, event.getDocument()); + LinesCols lc = storeLinesAndCols(event.getDocument(), fallback.getStartOffset(), fallback.getEndOffset()); if (lc == null) return null; translated = Pair.create(fallback, lc); diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java index df4477b0c226..788bb24ad3aa 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java @@ -16,7 +16,6 @@ package com.intellij.openapi.editor.impl; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.util.Segment; import org.jetbrains.annotations.NotNull; /** @@ -29,17 +28,18 @@ class PersistentRangeMarkerUtil { * identified by the given event. * * @param e event that describes document change - * @param rangeMarker target range marker which update strategy should be selected + * @param rangeStart target range marker start, for which update strategy should be selected + * @param rangeEnd target range marker end * @return true if target document range referenced by the given range marker should be translated via * diff algorithm; false otherwise */ - static boolean shouldTranslateViaDiff(@NotNull DocumentEvent e, @NotNull Segment rangeMarker) { + static boolean shouldTranslateViaDiff(@NotNull DocumentEvent e, int rangeStart, int rangeEnd) { if (e.isWholeTextReplaced()) { // Perform translation if the whole text is replaced. return true; } - if (e.getOffset() >= rangeMarker.getEndOffset() || e.getOffset() + e.getOldLength() <= rangeMarker.getStartOffset()) { + if (e.getOffset() >= rangeEnd || e.getOffset() + e.getOldLength() <= rangeStart) { // Don't perform complex processing if the change doesn't affect target range. return false; } diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java index 3ccefb207053..668eed5ebb89 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java @@ -21,6 +21,8 @@ import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.RangeMarkerEx; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; import com.intellij.openapi.util.ProperTextRange; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.UnfairTextRange; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.util.Processor; import org.jetbrains.annotations.NonNls; @@ -172,7 +174,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx protected void changedUpdateImpl(@NotNull DocumentEvent e) { if (!isValid()) return; - ProperTextRange newRange = applyChange(e, intervalStart(), intervalEnd(), isGreedyToLeft(), isGreedyToRight()); + TextRange newRange = applyChange(e, intervalStart(), intervalEnd(), isGreedyToLeft(), isGreedyToRight()); if (newRange == null) { invalidate(e); return; @@ -183,9 +185,9 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx } @Nullable - static ProperTextRange applyChange(@NotNull DocumentEvent e, int intervalStart, int intervalEnd, boolean isGreedyToLeft, boolean isGreedyToRight) { + static TextRange applyChange(@NotNull DocumentEvent e, int intervalStart, int intervalEnd, boolean isGreedyToLeft, boolean isGreedyToRight) { if (intervalStart == intervalEnd) { - return processIfOnePoint(e, intervalStart, intervalEnd, isGreedyToRight); + return processIfOnePoint(e, intervalStart, isGreedyToRight); } final int offset = e.getOffset(); @@ -194,26 +196,26 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx // changes after the end. if (intervalEnd < offset) { - return new ProperTextRange(intervalStart, intervalEnd); + return new UnfairTextRange(intervalStart, intervalEnd); } if (!isGreedyToRight && intervalEnd == offset) { // handle replaceString that was minimized and resulted in insertString at the range end if (e instanceof DocumentEventImpl && oldLength == 0 && ((DocumentEventImpl)e).getInitialStartOffset() < offset) { - return new ProperTextRange(intervalStart, intervalEnd + newLength); + return new UnfairTextRange(intervalStart, intervalEnd + newLength); } - return new ProperTextRange(intervalStart, intervalEnd); + return new UnfairTextRange(intervalStart, intervalEnd); } // changes before start if (intervalStart > offset + oldLength) { - return new ProperTextRange(intervalStart + newLength - oldLength, intervalEnd + newLength - oldLength); + return new UnfairTextRange(intervalStart + newLength - oldLength, intervalEnd + newLength - oldLength); } if (!isGreedyToLeft && intervalStart == offset + oldLength) { // handle replaceString that was minimized and resulted in insertString at the range start if (e instanceof DocumentEventImpl && oldLength == 0 && ((DocumentEventImpl)e).getInitialStartOffset() + ((DocumentEventImpl)e).getInitialOldLength() > offset) { - return new ProperTextRange(intervalStart - oldLength, intervalEnd + newLength - oldLength); + return new UnfairTextRange(intervalStart - oldLength, intervalEnd + newLength - oldLength); } - return new ProperTextRange(intervalStart + newLength - oldLength, intervalEnd + newLength - oldLength); + return new UnfairTextRange(intervalStart + newLength - oldLength, intervalEnd + newLength - oldLength); } // Changes inside marker's area. Expand/collapse. @@ -229,14 +231,14 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx } if (intervalEnd >= offset && intervalEnd <= offset + oldLength && intervalStart < offset) { - return new ProperTextRange(intervalStart, offset); + return new UnfairTextRange(intervalStart, offset); } return null; } @Nullable - private static ProperTextRange processIfOnePoint(@NotNull DocumentEvent e, int intervalStart, int intervalEnd, boolean greedyRight) { + private static TextRange processIfOnePoint(@NotNull DocumentEvent e, int intervalStart, boolean greedyRight) { int offset = e.getOffset(); int oldLength = e.getOldLength(); int oldEnd = offset + oldLength; @@ -245,14 +247,14 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx } if (offset == intervalStart && oldLength == 0 && greedyRight) { - return new ProperTextRange(intervalStart, intervalEnd + e.getNewLength()); + return new UnfairTextRange(intervalStart, intervalStart + e.getNewLength()); } if (intervalStart > oldEnd || intervalStart == oldEnd && oldLength > 0) { - return new ProperTextRange(intervalStart + e.getNewLength() - oldLength, intervalEnd + e.getNewLength() - oldLength); + return new UnfairTextRange(intervalStart + e.getNewLength() - oldLength, intervalStart + e.getNewLength() - oldLength); } - return new ProperTextRange(intervalStart, intervalEnd); + return new UnfairTextRange(intervalStart, intervalStart); } @NonNls diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java index c3a38325f298..318c5b786371 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java @@ -147,7 +147,7 @@ class AnchorElementInfo extends SelfElementInfo { @Nullable @Override - public ProperTextRange getPsiRange() { + public TextRange getPsiRange() { if (getStubId() != -1) { switchToTree(); } diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/MarkerCache.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/MarkerCache.java index dd2c0028bb71..f8e612759449 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/MarkerCache.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/MarkerCache.java @@ -20,9 +20,9 @@ import com.intellij.openapi.editor.impl.FrozenDocument; import com.intellij.openapi.editor.impl.ManualRangeMarker; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; import com.intellij.openapi.editor.impl.event.RetargetRangeMarkers; -import com.intellij.openapi.util.ProperTextRange; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.UnfairTextRange; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -94,11 +94,12 @@ class MarkerCache { while (i < markers.length) { SelfElementInfo info = infos.get(i); boolean forInjected = info.isForInjected(); - ProperTextRange range = ObjectUtils.assertNotNull(info.getPsiRange()); - markers[i] = new ManualRangeMarker(range, forInjected, forInjected, !forInjected, null); + int start = info.getPsiStartOffset(); + int end = info.getPsiEndOffset(); + markers[i] = new ManualRangeMarker(start, end, forInjected, forInjected, !forInjected, null); i++; - while (i < markers.length && rangeEquals(infos.get(i), range, forInjected)) { + while (i < markers.length && rangeEquals(infos.get(i), start, end, forInjected)) { markers[i] = markers[i - 1]; i++; } @@ -106,8 +107,8 @@ class MarkerCache { return markers; } - private static boolean rangeEquals(SelfElementInfo info, ProperTextRange range, boolean injected) { - return range.getStartOffset() == info.getPsiStartOffset() && range.getEndOffset() == info.getPsiEndOffset() && injected == info.isForInjected(); + private static boolean rangeEquals(SelfElementInfo info, int start, int end, boolean injected) { + return start == info.getPsiStartOffset() && end == info.getPsiEndOffset() && injected == info.isForInjected(); } private static UpdatedRanges applyEvents(@NotNull List events, final UpdatedRanges struct) { @@ -150,8 +151,7 @@ class MarkerCache { UpdatedRanges updated = getUpdatedMarkers(frozen, events); for (int i = 0; i < updated.myMarkers.length; i++) { - ManualRangeMarker newRangeMarker = updated.myMarkers[i]; - updated.mySortedInfos.get(i).setRange(newRangeMarker == null ? null : newRangeMarker.getRange()); + updated.mySortedInfos.get(i).setRange(updated.myMarkers[i]); } myUpdatedRanges = null; @@ -176,11 +176,11 @@ class MarkerCache { } @Nullable - ProperTextRange getUpdatedRange(@NotNull SelfElementInfo info, @NotNull FrozenDocument frozen, @NotNull List events) { + TextRange getUpdatedRange(@NotNull SelfElementInfo info, @NotNull FrozenDocument frozen, @NotNull List events) { UpdatedRanges struct = getUpdatedMarkers(frozen, events); int i = Collections.binarySearch(struct.mySortedInfos, info, BY_RANGE_KEY); ManualRangeMarker updated = i >= 0 ? struct.myMarkers[i] : null; - return updated == null ? null : updated.getRange(); + return updated == null ? null : new UnfairTextRange(updated.getStartOffset(), updated.getEndOffset()); } void rangeChanged() { diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java index a704c2ae27f7..414c3d3c8ca3 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java @@ -102,13 +102,13 @@ public class SelfElementInfo extends SmartPointerElementInfo { @Nullable @Override - public ProperTextRange getPsiRange() { + public TextRange getPsiRange() { return calcPsiRange(); } @Nullable - private ProperTextRange calcPsiRange() { - return hasRange() ? ProperTextRange.create(myStartOffset, myEndOffset) : null; + private TextRange calcPsiRange() { + return hasRange() ? new UnfairTextRange(myStartOffset, myEndOffset) : null; } @Override 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 654101355827..4cde8efbcf51 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 @@ -59,7 +59,7 @@ class PersistentRangeHighlighterImpl extends RangeHighlighterImpl implements Ran protected void changedUpdateImpl(@NotNull DocumentEvent e) { // todo Denis Zhdanov DocumentEventImpl event = (DocumentEventImpl)e; - final boolean shouldTranslateViaDiff = isValid() && PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, this); + final boolean shouldTranslateViaDiff = isValid() && PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, getStartOffset(), getEndOffset()); boolean wasTranslatedViaDiff = shouldTranslateViaDiff; if (shouldTranslateViaDiff) { wasTranslatedViaDiff = translatedViaDiff(e, event);