calculate line/column information for persistent range markers only when it's really needed (rarely) (IDEA-49250)

This commit is contained in:
peter
2015-10-16 09:10:42 +02:00
parent 3e8df3f6c7
commit 0d9b61beec
3 changed files with 29 additions and 25 deletions
@@ -16,6 +16,7 @@
package com.intellij.openapi.editor.impl;
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;
@@ -23,47 +24,49 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A range marker that has to be manually updated with {@link #getUpdatedRange(DocumentEvent)}.
* 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;
private final boolean myGreedyLeft;
private final boolean myGreedyRight;
private final boolean mySurviveOnExternalChange;
private final PersistentRangeMarker.LinesCols myLinesCols;
public ManualRangeMarker(@NotNull FrozenDocument document, @NotNull ProperTextRange range, boolean greedyLeft, boolean greedyRight, boolean surviveOnExternalChange) {
this(range, greedyLeft, greedyRight, surviveOnExternalChange ? PersistentRangeMarker.storeLinesAndCols(range, document) : null);
}
private ManualRangeMarker(@NotNull ProperTextRange range,
public ManualRangeMarker(@NotNull ProperTextRange range,
boolean greedyLeft,
boolean greedyRight,
boolean surviveOnExternalChange,
@Nullable PersistentRangeMarker.LinesCols linesCols) {
myRange = range;
myGreedyLeft = greedyLeft;
myGreedyRight = greedyRight;
mySurviveOnExternalChange = surviveOnExternalChange;
myLinesCols = linesCols;
}
@Nullable
public ManualRangeMarker getUpdatedRange(@NotNull DocumentEvent event) {
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, myLinesCols == null ? null : PersistentRangeMarker.storeLinesAndCols(range, event.getDocument()));
return new ManualRangeMarker(range, myGreedyLeft, myGreedyRight, mySurviveOnExternalChange, null);
}
}
if (myLinesCols != null) {
Pair<ProperTextRange, PersistentRangeMarker.LinesCols> pair = PersistentRangeMarker
.applyChange(event, myRange, myRange.getStartOffset(), myRange.getEndOffset(), myGreedyLeft, myGreedyRight, myLinesCols);
return pair == null ? null : new ManualRangeMarker(pair.first, myGreedyLeft, myGreedyRight, pair.second);
if (mySurviveOnExternalChange && PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, myRange)) {
PersistentRangeMarker.LinesCols linesCols = myLinesCols != null ? myLinesCols
: PersistentRangeMarker.storeLinesAndCols(myRange, documentBefore);
Pair<ProperTextRange, PersistentRangeMarker.LinesCols> pair = PersistentRangeMarker.translateViaDiff((DocumentEventImpl)event, linesCols);
if (pair != null) {
return new ManualRangeMarker(pair.first, 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, null);
return range == null ? null : new ManualRangeMarker(range, myGreedyLeft, myGreedyRight, mySurviveOnExternalChange, null);
}
@NotNull
@@ -79,7 +79,7 @@ class PersistentRangeMarker extends RangeMarkerImpl {
}
@Nullable
private static Pair<ProperTextRange, LinesCols> translateViaDiff(final DocumentEventImpl event, LinesCols linesCols) {
static Pair<ProperTextRange, LinesCols> translateViaDiff(final DocumentEventImpl event, LinesCols linesCols) {
try {
int myStartLine = event.translateLineViaDiffStrict(linesCols.myStartLine);
Document document = event.getDocument();
@@ -98,6 +98,13 @@ class PersistentRangeMarker extends RangeMarkerImpl {
int end = document.getLineStartOffset(myEndLine) + linesCols.myEndColumn;
if (end > document.getTextLength() || end < start) return null;
if (end > event.getDocument().getTextLength() ||
myEndLine < myStartLine ||
myStartLine == myEndLine && linesCols.myEndColumn < linesCols.myStartColumn ||
event.getDocument().getLineCount() < myEndLine) {
return null;
}
return Pair.create(new ProperTextRange(start, end), new LinesCols(myStartLine, linesCols.myStartColumn, myEndLine, linesCols.myEndColumn));
}
catch (FilesTooBigForDiffException e) {
@@ -122,7 +129,7 @@ class PersistentRangeMarker extends RangeMarkerImpl {
}
@Nullable
static Pair<ProperTextRange, LinesCols> applyChange(DocumentEvent event, Segment range, int intervalStart, int intervalEnd, boolean greedyLeft, boolean greedyRight, LinesCols linesCols) {
private static Pair<ProperTextRange, LinesCols> applyChange(DocumentEvent event, Segment range, int intervalStart, int intervalEnd, boolean greedyLeft, boolean greedyRight, LinesCols linesCols) {
final boolean shouldTranslateViaDiff = PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, range);
Pair<ProperTextRange, LinesCols> translated = null;
if (shouldTranslateViaDiff) {
@@ -137,13 +144,6 @@ class PersistentRangeMarker extends RangeMarkerImpl {
translated = Pair.create(fallback, lc);
}
if (translated.first.getEndOffset() > event.getDocument().getTextLength() ||
translated.second.myEndLine < translated.second.myStartLine ||
translated.second.myStartLine == translated.second.myEndLine && translated.second.myEndColumn < translated.second.myStartColumn ||
event.getDocument().getLineCount() < translated.second.myEndLine) {
return null;
}
return translated;
}
@@ -71,7 +71,7 @@ class MarkerCache {
long key = info.markerCacheKey();
if (range != null && key != 0) {
boolean forInjected = info.isForInjected();
answer.put(key, new ManualRangeMarker(frozen, range, forInjected, forInjected, !forInjected));
answer.put(key, new ManualRangeMarker(range, forInjected, forInjected, !forInjected, null));
}
}
frozen = applyEvents(frozen, events, answer);
@@ -86,6 +86,7 @@ class MarkerCache {
@NotNull List<DocumentEvent> events,
final TLongObjectHashMap<ManualRangeMarker> map) {
for (DocumentEvent event : events) {
final FrozenDocument before = frozen;
final DocumentEvent corrected;
if ((event instanceof RetargetRangeMarkers)) {
RetargetRangeMarkers retarget = (RetargetRangeMarkers)event;
@@ -101,7 +102,7 @@ class MarkerCache {
map.transformValues(new TObjectFunction<ManualRangeMarker, ManualRangeMarker>() {
@Override
public ManualRangeMarker execute(ManualRangeMarker currentRange) {
return currentRange == null ? null : currentRange.getUpdatedRange(corrected);
return currentRange == null ? null : currentRange.getUpdatedRange(corrected, before);
}
});
}