mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
calculate line/column information for persistent range markers only when it's really needed (rarely) (IDEA-49250)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user