mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
stricter validation in folding model on adding fold regions
This commit is contained in:
@@ -59,11 +59,11 @@ public class FoldingUpdate {
|
||||
private static final Key<ParameterizedCachedValue<Runnable, Couple<Boolean>>> CODE_FOLDING_KEY = Key.create("code folding");
|
||||
private static final Key<String> CODE_FOLDING_FILE_EXTENSION_KEY = Key.create("code folding file extension");
|
||||
|
||||
private static final Comparator<PsiElement> COMPARE_BY_OFFSET = new Comparator<PsiElement>() {
|
||||
private static final Comparator<PsiElement> COMPARE_BY_OFFSET_REVERSED = new Comparator<PsiElement>() {
|
||||
@Override
|
||||
public int compare(PsiElement element, PsiElement element1) {
|
||||
int startOffsetDiff = element.getTextRange().getStartOffset() - element1.getTextRange().getStartOffset();
|
||||
return startOffsetDiff == 0 ? element.getTextRange().getEndOffset() - element1.getTextRange().getEndOffset() : startOffsetDiff;
|
||||
int startOffsetDiff = element1.getTextRange().getStartOffset() - element.getTextRange().getStartOffset();
|
||||
return startOffsetDiff == 0 ? element1.getTextRange().getEndOffset() - element.getTextRange().getEndOffset() : startOffsetDiff;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -284,7 +284,7 @@ public class FoldingUpdate {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<PsiElement, Collection<FoldingDescriptor>> createMap() {
|
||||
return new TreeMap<PsiElement, Collection<FoldingDescriptor>>(COMPARE_BY_OFFSET);
|
||||
return new TreeMap<PsiElement, Collection<FoldingDescriptor>>(COMPARE_BY_OFFSET_REVERSED);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -17,8 +17,6 @@ package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.FoldRegion;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,8 +30,6 @@ import java.util.*;
|
||||
abstract class FoldRegionsTree {
|
||||
@NotNull private CachedData myCachedData = new CachedData();
|
||||
|
||||
int myCachedLastIndex = -1;
|
||||
|
||||
//sorted using RangeMarker.BY_START_OFFSET comparator
|
||||
//i.e., first by start offset, then, if start offsets are equal, by end offset
|
||||
@NotNull
|
||||
@@ -67,8 +63,6 @@ abstract class FoldRegionsTree {
|
||||
|
||||
protected abstract boolean isFoldingEnabled();
|
||||
|
||||
protected abstract boolean isBatchFoldingProcessing();
|
||||
|
||||
void rebuild() {
|
||||
List<FoldRegion> topLevels = new ArrayList<FoldRegion>(myRegions.size() / 2);
|
||||
List<FoldRegion> visible = new ArrayList<FoldRegion>(myRegions.size());
|
||||
@@ -165,43 +159,38 @@ abstract class FoldRegionsTree {
|
||||
}
|
||||
|
||||
boolean addRegion(@NotNull FoldRegion range) {
|
||||
// During batchProcessing elements are inserted in ascending order,
|
||||
// binary search find acceptable insertion place first time
|
||||
boolean canUseCachedValue = false;
|
||||
if (isBatchFoldingProcessing() && myCachedLastIndex >= 0 && myCachedLastIndex < myRegions.size()) {
|
||||
FoldRegion lastRegion = myRegions.get(myCachedLastIndex);
|
||||
if (RangeMarker.BY_START_OFFSET.compare(lastRegion, range) < 0) {
|
||||
canUseCachedValue = myCachedLastIndex == (myRegions.size() - 1)
|
||||
|| RangeMarker.BY_START_OFFSET.compare(range, myRegions.get(myCachedLastIndex + 1)) <= 0;
|
||||
int start = range.getStartOffset();
|
||||
int end = range.getEndOffset();
|
||||
int insertionIndex = myRegions.size();
|
||||
for (int i = 0; i < myRegions.size(); i++) {
|
||||
FoldRegion region = myRegions.get(i);
|
||||
int rStart = region.getStartOffset();
|
||||
int rEnd = region.getEndOffset();
|
||||
if (rStart < start) {
|
||||
if (region.isValid() && start < rEnd && rEnd < end) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
int index = canUseCachedValue ? myCachedLastIndex + 1 : Collections.binarySearch(myRegions, range, RangeMarker.BY_START_OFFSET);
|
||||
if (index < 0) index = -index - 1;
|
||||
|
||||
if (index < myRegions.size()) {
|
||||
FoldRegion foldRegion = myRegions.get(index);
|
||||
if (TextRange.areSegmentsEqual(foldRegion, range)) {
|
||||
return false;
|
||||
else if (rStart == start) {
|
||||
if (rEnd == end) {
|
||||
return false;
|
||||
}
|
||||
else if (rEnd > end) {
|
||||
insertionIndex = Math.min(insertionIndex, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = index - 1; i >=0; --i) {
|
||||
final FoldRegion region = myRegions.get(i);
|
||||
if (region.getEndOffset() < range.getStartOffset()) break;
|
||||
if (region.isValid() && intersects(region, range)) {
|
||||
return false;
|
||||
else {
|
||||
insertionIndex = Math.min(insertionIndex, i);
|
||||
if (rStart > end) {
|
||||
break;
|
||||
}
|
||||
if (region.isValid() && rStart < end && end < rEnd) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = index; i < myRegions.size(); i++) {
|
||||
final FoldRegion region = myRegions.get(i);
|
||||
if (region.getStartOffset() > range.getEndOffset()) break;
|
||||
if (region.isValid() && intersects(region, range)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
myRegions.add(myCachedLastIndex = index,range);
|
||||
myRegions.add(insertionIndex, range);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -249,14 +238,6 @@ abstract class FoldRegionsTree {
|
||||
return outer.getStartOffset() <= inner.getStartOffset() && outer.getEndOffset() >= inner.getEndOffset();
|
||||
}
|
||||
|
||||
private static boolean intersects(FoldRegion r1, FoldRegion r2) {
|
||||
final int s1 = r1.getStartOffset();
|
||||
final int s2 = r2.getStartOffset();
|
||||
final int e1 = r1.getEndOffset();
|
||||
final int e2 = r2.getEndOffset();
|
||||
return s1 < s2 && s2 < e1 && e1 < e2 || s2 < s1 && s1 < e2 && e2 < e1;
|
||||
}
|
||||
|
||||
static boolean contains(FoldRegion region, int offset) {
|
||||
return region.getStartOffset() < offset && region.getEndOffset() > offset;
|
||||
}
|
||||
|
||||
@@ -79,11 +79,6 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList
|
||||
protected boolean isFoldingEnabled() {
|
||||
return FoldingModelImpl.this.isFoldingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isBatchFoldingProcessing() {
|
||||
return myIsBatchFoldingProcessing;
|
||||
}
|
||||
};
|
||||
myFoldRegionsProcessed = false;
|
||||
refreshSettings();
|
||||
@@ -210,12 +205,9 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList
|
||||
}
|
||||
|
||||
myIsBatchFoldingProcessing = true;
|
||||
myFoldTree.myCachedLastIndex = -1;
|
||||
try {
|
||||
operation.run();
|
||||
} finally {
|
||||
myFoldTree.myCachedLastIndex = -1;
|
||||
|
||||
if (!oldBatchFlag) {
|
||||
if (myFoldRegionsProcessed) {
|
||||
notifyBatchFoldingProcessingDone(moveCaret);
|
||||
|
||||
@@ -86,6 +86,20 @@ public class FoldingTest extends AbstractEditorTest {
|
||||
});
|
||||
}
|
||||
|
||||
public void testIntersectsWithRegionFarInStorageOrder() {
|
||||
myModel.runBatchFoldingOperation(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FoldRegion region = myModel.addFoldRegion(0, 10, ".");
|
||||
assertNotNull(region);
|
||||
region = myModel.addFoldRegion(1, 5, ".");
|
||||
assertNotNull(region);
|
||||
region = myModel.addFoldRegion(6, 11, ".");
|
||||
assertNull(region);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testAddEmptyRegion() {
|
||||
FoldRegion region = null;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user