diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java index 62f641b37807..07bd92cb687a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java @@ -59,11 +59,11 @@ public class FoldingUpdate { private static final Key>> CODE_FOLDING_KEY = Key.create("code folding"); private static final Key CODE_FOLDING_FILE_EXTENSION_KEY = Key.create("code folding file extension"); - private static final Comparator COMPARE_BY_OFFSET = new Comparator() { + private static final Comparator COMPARE_BY_OFFSET_REVERSED = new Comparator() { @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> createMap() { - return new TreeMap>(COMPARE_BY_OFFSET); + return new TreeMap>(COMPARE_BY_OFFSET_REVERSED); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java index d9522f90c4de..758447179367 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java @@ -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 topLevels = new ArrayList(myRegions.size() / 2); List visible = new ArrayList(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; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java index 7dbd0e3e9211..153d3a9405e4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java @@ -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); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java index 2f0ee4cebc01..9409cf539c7b 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java @@ -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 {