diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/FoldingModel.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/FoldingModel.java
index dca85b604208..0720134b2e08 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/FoldingModel.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/FoldingModel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,11 +33,19 @@ public interface FoldingModel {
* @param startOffset the start offset of the region to fold.
* @param endOffset the end offset of the region to fold.
* @param placeholderText the text to display instead of the region contents when the region is folded.
- * @return the fold region, or null if folding is currently disabled.
+ * @return the fold region, or null if folding is currently disabled or corresponding region cannot be added (e.g. if it
+ * intersects with another existing region)
*/
@Nullable
FoldRegion addFoldRegion(int startOffset, int endOffset, @NotNull String placeholderText);
+ /**
+ * Tries to add given region to the folding model. This method must be called
+ * from the Runnable passed to {@link #runBatchFoldingOperation(Runnable)}.
+ *
+ * @return true, if region was added successfully, false if the region cannot be added, e.g. if it
+ * intersects with another existing region
+ */
boolean addFoldRegion(@NotNull FoldRegion region);
/**
@@ -57,13 +65,22 @@ public interface FoldingModel {
FoldRegion[] getAllFoldRegions();
/**
- * Checks if the specified offset in the document belongs to a folded region.
+ * Checks if the specified offset in the document belongs to a folded region. The region must contain given offset or be located right
+ * after given offset, i.e. the following condition must hold: foldStartOffset <= offset < foldEndOffset.
*
* @param offset the offset to check.
* @return true if the offset belongs to a folded region, false otherwise.
+ *
+ * @see #getCollapsedRegionAtOffset(int)
*/
boolean isOffsetCollapsed(int offset);
+ /**
+ * Returns collapsed folded region at a given offset or null if there's no such region. Returned region will satisfy the
+ * following condition: region.getStartOffset() <= offset < region.getEndOffset()
+ *
+ * @see #isOffsetCollapsed(int)
+ */
@Nullable
FoldRegion getCollapsedRegionAtOffset(int offset);
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 e9987064169f..6c959e3e2ad8 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,11 @@ abstract class FoldRegionsTree {
private int[] myCachedStartOffsets;
private int[] myCachedFoldedLines;
int myCachedLastIndex = -1;
- private ArrayList myRegions = ContainerUtil.newArrayList(); //sorted in tree left-to-right topdown traversal order
+
+ //sorted using RangeMarker.BY_START_OFFSET comparator
+ //i.e., first by start offset, then, if start offsets are equal, by end offset
+ private ArrayList myRegions = ContainerUtil.newArrayList();
+
private static final Comparator BY_END_OFFSET = new Comparator() {
@Override
public int compare(FoldRegion r1, FoldRegion r2) {
@@ -89,13 +93,15 @@ abstract class FoldRegionsTree {
}
allValid.add(region);
-
+
+ if (!region.isExpanded()) {
+ removeRegionsWithSameStartOffset(visible, region);
+ removeRegionsWithSameStartOffset(topLevels, region);
+ }
+
if (currentCollapsed == null || !contains(currentCollapsed, region)) {
visible.add(region);
- }
-
- if (!region.isExpanded()) {
- if (currentCollapsed == null || currentCollapsed.getEndOffset() < region.getStartOffset()) {
+ if (!region.isExpanded()) {
currentCollapsed = region;
topLevels.add(region);
}
@@ -115,6 +121,17 @@ abstract class FoldRegionsTree {
updateCachedOffsets();
}
+ private static void removeRegionsWithSameStartOffset(List regions, FoldRegion region) {
+ for (int i = regions.size() - 1; i >= 0 ; i--) {
+ if (regions.get(i).getStartOffset() == region.getStartOffset()) {
+ regions.remove(i);
+ }
+ else {
+ break;
+ }
+ }
+ }
+
@NotNull
private static FoldRegion[] toFoldArray(@NotNull List topLevels) {
return topLevels.isEmpty() ? FoldRegion.EMPTY_ARRAY : topLevels.toArray(new FoldRegion[topLevels.size()]);
@@ -164,31 +181,25 @@ abstract class FoldRegionsTree {
boolean addRegion(FoldRegion range) {
// During batchProcessing elements are inserted in ascending order,
// binary search find acceptable insertion place first time
- final boolean canUseCachedValue;
- if (myCachedLastIndex >= myRegions.size()) {
- // todo this happens after removeRegion()... myCachedListIndex must die!
- canUseCachedValue = false;
+ 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;
+ }
}
- else {
- canUseCachedValue =
- myCachedLastIndex != -1 && isBatchFoldingProcessing() && myRegions.get(myCachedLastIndex).getStartOffset() <= range.getStartOffset();
- }
- int fastIndex = canUseCachedValue ? myCachedLastIndex + 1 : Collections.binarySearch(myRegions, range, RangeMarker.BY_START_OFFSET);
- if (fastIndex < 0) fastIndex = -fastIndex - 1;
-
- // There is a possible case that given range is the first at the current batch iteration. It's also possible that it
- // range with the same bounds is already registered (e.g. particular range is registered during 'build initial fold regions' phase
- // and given range has the same offsets but different 'expanded' status.
- // We explicitly check for such situation, remove existing region and add the given one instead.
- if (fastIndex < myRegions.size()) {
- FoldRegion foldRegion = myRegions.get(fastIndex);
+ 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)) {
- removeRegion(foldRegion);
- return addRegion(range);
- }
+ return false;
+ }
}
- for (int i = fastIndex - 1; i >=0; --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)) {
@@ -196,28 +207,15 @@ abstract class FoldRegionsTree {
}
}
- for (int i = fastIndex; i < myRegions.size(); i++) {
+ for (int i = index; i < myRegions.size(); i++) {
final FoldRegion region = myRegions.get(i);
-
- if (range.getStartOffset() < region.getStartOffset() ||
- range.getStartOffset() == region.getStartOffset() && range.getEndOffset() > region.getEndOffset()) {
- for (int j = i + 1; j < myRegions.size(); j++) {
- final FoldRegion next = myRegions.get(j);
- if (next.getEndOffset() >= range.getEndOffset() && next.isValid()) {
- if (next.getStartOffset() < range.getStartOffset()) {
- return false;
- }
- else {
- break;
- }
- }
- }
-
- myRegions.add(myCachedLastIndex = i, range);
- return true;
+ if (region.getStartOffset() > range.getEndOffset()) break;
+ if (region.isValid() && intersects(region, range)) {
+ return false;
}
}
- myRegions.add(myCachedLastIndex = myRegions.size(),range);
+
+ myRegions.add(myCachedLastIndex = index,range);
return true;
}
@@ -274,7 +272,7 @@ abstract class FoldRegionsTree {
}
private static boolean contains(FoldRegion outer, FoldRegion inner) {
- return outer.getStartOffset() < inner.getStartOffset() && outer.getEndOffset() > inner.getStartOffset();
+ return outer.getStartOffset() <= inner.getStartOffset() && outer.getEndOffset() >= inner.getEndOffset();
}
private static boolean intersects(FoldRegion r1, FoldRegion r2) {
@@ -282,7 +280,7 @@ abstract class FoldRegionsTree {
final int s2 = r2.getStartOffset();
final int e1 = r1.getEndOffset();
final int e2 = r2.getEndOffset();
- return s1 == s2 && e1 == e2 || s1 < s2 && s2 < e1 && e1 < e2 || s2 < s1 && s1 < e2 && e2 < e1;
+ return s1 < s2 && s2 < e1 && e1 < e2 || s2 < s1 && s1 < e2 && e2 < e1;
}
static boolean contains(FoldRegion region, int offset) {
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingStressTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingStressTest.java
new file mode 100644
index 000000000000..3eff9286d246
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingStressTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor;
+
+import com.intellij.openapi.editor.impl.DocumentImpl;
+import com.intellij.testFramework.LightPlatformTestCase;
+import com.intellij.testFramework.PlatformTestCase;
+
+public class FoldingStressTest extends LightPlatformTestCase {
+
+ static {
+ PlatformTestCase.autodetectPlatformPrefix();
+ }
+
+ public void testStressFoldingFromZeroOffset() throws Exception {
+ for (int len = 2; len < 25; len++) {
+ stress(len);
+ }
+ }
+
+ public void testStress8() throws Exception {
+ DocumentImpl doc = new DocumentImpl("0123456789\n123456789\n23456789");
+ Editor editor = EditorFactory.getInstance().createEditor(doc);
+ try {
+ final FoldingModel model = editor.getFoldingModel();
+ model.runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ addAndCollapseFoldRegion(model, 0, 8, "/*...*/");
+ addAndCollapseFoldRegion(model, 10, 12, "/*...*/");
+ }
+ });
+
+ assertEquals(10, editor.logicalPositionToOffset(new LogicalPosition(0, 10)));
+
+ for (int line = 0; line <= 3; line++) {
+ for (int column = 0; column <= 100; column++) {
+ LogicalPosition log = new LogicalPosition(line, column);
+ editor.logicalToVisualPosition(log);
+ }
+ }
+ }
+ finally {
+ EditorFactory.getInstance().releaseEditor(editor);
+ }
+ }
+
+ private static void stress(final int len) {
+ DocumentImpl doc = new DocumentImpl("0123456789\n123456789\n23456789");
+ Editor editor = EditorFactory.getInstance().createEditor(doc);
+ try {
+ final FoldingModel model = editor.getFoldingModel();
+ model.runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ addAndCollapseFoldRegion(model, 0, len, "/*...*/");
+ addAndCollapseFoldRegion(model, len + 2, len + 4, "/*...*/");
+ }
+ });
+
+ for (int line = 0; line <= 3; line++) {
+ for (int column = 0; column <= 100; column++) {
+ LogicalPosition log = new LogicalPosition(line, column);
+ editor.logicalToVisualPosition(log);
+ }
+ }
+ }
+ finally {
+ EditorFactory.getInstance().releaseEditor(editor);
+ }
+ }
+
+ private static void addAndCollapseFoldRegion(FoldingModel model, int startOffset, int endOffset, String placeHolder) {
+ FoldRegion foldRegion = model.addFoldRegion(startOffset, endOffset, placeHolder);
+ assertNotNull(foldRegion);
+ foldRegion.setExpanded(false);
+ }
+
+}
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 d9fb2c5cb29c..5864112f9faa 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java
@@ -1,182 +1,153 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.intellij.openapi.editor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.ex.FoldingModelEx;
-import com.intellij.openapi.editor.impl.DocumentImpl;
-import com.intellij.openapi.util.Ref;
-import com.intellij.testFramework.LightPlatformTestCase;
+import com.intellij.openapi.editor.impl.AbstractEditorTest;
import com.intellij.testFramework.PlatformTestCase;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.testFramework.TestFileType;
+
+import static org.junit.Assert.assertArrayEquals;
/**
* @author max
*/
-public class FoldingTest extends LightPlatformTestCase {
-
+public class FoldingTest extends AbstractEditorTest {
static {
PlatformTestCase.autodetectPlatformPrefix();
}
- public void testStressFoldingFromZeroOffset() throws Exception {
- for (int len = 2; len < 25; len++) {
- stress(len);
- }
- }
+ private FoldingModelEx myModel;
- public void testStress8() throws Exception {
- DocumentImpl doc = new DocumentImpl("0123456789\n123456789\n23456789");
- Editor editor = EditorFactory.getInstance().createEditor(doc);
- try {
- final FoldingModel model = editor.getFoldingModel();
- model.runBatchFoldingOperation(new Runnable() {
- @Override
- public void run() {
- model.addFoldRegion(0, 8, "/*...*/").setExpanded(false);
- model.addFoldRegion(10, 12, "/*...*/").setExpanded(false);
- }
- });
-
- assertEquals(10, editor.logicalPositionToOffset(new LogicalPosition(0, 10)));
-
- for (int line = 0; line <= 3; line++) {
- for (int column = 0; column <= 100; column++) {
- LogicalPosition log = new LogicalPosition(line, column);
- editor.logicalToVisualPosition(log);
- }
- }
- }
- finally {
- EditorFactory.getInstance().releaseEditor(editor);
- }
- }
-
- private static void stress(final int len) {
- DocumentImpl doc = new DocumentImpl("0123456789\n123456789\n23456789");
- Editor editor = EditorFactory.getInstance().createEditor(doc);
- try {
- final FoldingModel model = editor.getFoldingModel();
- model.runBatchFoldingOperation(new Runnable() {
- @Override
- public void run() {
- model.addFoldRegion(0, len, "/*...*/").setExpanded(false);
- model.addFoldRegion(len + 2, len + 4, "/*...*/").setExpanded(false);
- }
- });
-
- for (int line = 0; line <= 3; line++) {
- for (int column = 0; column <= 100; column++) {
- LogicalPosition log = new LogicalPosition(line, column);
- editor.logicalToVisualPosition(log);
- }
- }
- }
- finally {
- EditorFactory.getInstance().releaseEditor(editor);
- }
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ init("I don't know what you mean by `glory,'\" Alice said" +
+ "Humpty Dumpty smiled contemptuously. \"Of course you don't -- till I tell you. I meant `there's a nice knock-down argument for you!'" +
+ "But glory doesn't mean `a nice knock-down argument,'\" Alice objected." +
+ "When I use a word,\" Humpty Dumpty said, in a rather scornful tone, \"it means just what I choose it to mean -- neither more nor less." +
+ "The question is,\" said Alice, \"whether you can make words mean so many different things." +
+ "The question is,\" said Humpty Dumpty, \"which is to be master -- that's all.",
+ TestFileType.TEXT);
+ myModel = (FoldingModelEx)myEditor.getFoldingModel();
}
public void testCleanupInvalidRegions() {
- final DocumentImpl doc = new DocumentImpl("foo1\nfoo2\nfoo3\nfoo4");
- Editor editor = EditorFactory.getInstance().createEditor(doc);
- final FoldingModel model = editor.getFoldingModel();
- try {
- model.runBatchFoldingOperation(new Runnable() {
- @Override
- public void run() {
- model.addFoldRegion(0, 4, "/*...*/");
- model.addFoldRegion(5, 9, "/*...*/");
- }
- });
- assertSize(2, model.getAllFoldRegions());
- WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
- @Override
- public void run() {
- doc.deleteString(0, 5);
- }
- });
- assertSize(1, model.getAllFoldRegions());
- }
- finally {
- EditorFactory.getInstance().releaseEditor(editor);
- }
+ myModel.runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ myModel.addFoldRegion(0, 4, "/*...*/");
+ myModel.addFoldRegion(5, 9, "/*...*/");
+ }
+ });
+ assertSize(2, myModel.getAllFoldRegions());
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ myEditor.getDocument().deleteString(0, 5);
+ }
+ });
+ assertSize(1, myModel.getAllFoldRegions());
}
public void testIntersects () throws Exception {
- @NonNls DocumentImpl doc = new DocumentImpl("I don't know what you mean by `glory,'\" Alice said" +
- "Humpty Dumpty smiled contemptuously. \"Of course you don't -- till I tell you. I meant `there's a nice knock-down argument for you!'" +
- "But glory doesn't mean `a nice knock-down argument,'\" Alice objected." +
- "When I use a word,\" Humpty Dumpty said, in a rather scornful tone, \"it means just what I choose it to mean -- neither more nor less." +
- "The question is,\" said Alice, \"whether you can make words mean so many different things." +
- "The question is,\" said Humpty Dumpty, \"which is to be master -- that's all." );
- Editor editor = EditorFactory.getInstance().createEditor(doc);
- try {
- final FoldingModel model = editor.getFoldingModel();
-
- model.runBatchFoldingOperation(new Runnable() {
- @Override
- public void run() {
- FoldRegion region = model.addFoldRegion(5, 10, ".");
- assertNotNull(region);
- region = model.addFoldRegion(7, 11, ".");
- assertNull(region);
- region = model.addFoldRegion(20, 30, ".");
- assertNotNull(region);
- region = model.addFoldRegion(9, 12, ".");
- assertNull(region);
- region = model.addFoldRegion(7, 10, ".");
- assertNotNull(region);
- region = model.addFoldRegion(7, 10, ".");
- assertNull(region);
- region = model.addFoldRegion(5, 30, ".");
- assertNotNull(region);
- }
- });
- }
- finally {
- EditorFactory.getInstance().releaseEditor(editor);
- }
+ myModel.runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ FoldRegion region = myModel.addFoldRegion(5, 10, ".");
+ assertNotNull(region);
+ region = myModel.addFoldRegion(7, 11, ".");
+ assertNull(region);
+ region = myModel.addFoldRegion(20, 30, ".");
+ assertNotNull(region);
+ region = myModel.addFoldRegion(9, 12, ".");
+ assertNull(region);
+ region = myModel.addFoldRegion(7, 10, ".");
+ assertNotNull(region);
+ region = myModel.addFoldRegion(7, 10, ".");
+ assertNull(region);
+ region = myModel.addFoldRegion(5, 30, ".");
+ assertNotNull(region);
+ }
+ });
}
- public void testDuplicateRegions() {
- StringBuilder text = new StringBuilder();
- for (int i = 0; i < 450; i++) {
- text.append('a');
- }
- Editor editor = EditorFactory.getInstance().createEditor(new DocumentImpl(text));
+ public void testAddEmptyRegion() {
+ FoldRegion region = null;
try {
- final Ref expandedStatus = new Ref();
- final int startOffset = 6;
- final int endOffset = 16;
- final FoldingModelEx model = (FoldingModelEx)editor.getFoldingModel();
- model.runBatchFoldingOperation(new Runnable() {
- @Override
- public void run() {
- model.addFoldRegion(2, 20, "..");
- model.addFoldRegion(4, 18, "..");
- FoldRegion oldRegion = model.addFoldRegion(startOffset, endOffset, "..");
- assertNotNull(oldRegion);
- expandedStatus.set(!oldRegion.isExpanded());
- }
- });
- assertEquals(3, model.getAllFoldRegions().length);
-
- final Ref newRegion = new Ref();
- model.runBatchFoldingOperation(new Runnable() {
- @Override
- public void run() {
- newRegion.set(model.createFoldRegion(startOffset, endOffset, "..", null, false));
- assertNotNull(newRegion.get());
- newRegion.get().setExpanded(expandedStatus.get());
- boolean additionFlag = model.addFoldRegion(newRegion.get());
- assertTrue(additionFlag);
- }
- });
- FoldRegion fetched = model.fetchOutermost(startOffset);
- assertSame(newRegion.get(), fetched);
- assertEquals(3, model.getAllFoldRegions().length);
+ region = myModel.addFoldRegion(5, 5, "...");
}
- finally {
- EditorFactory.getInstance().releaseEditor(editor);
+ catch (AssertionError ignored) {
}
+ assertNull(region);
+ }
+
+ public void testCollapsedRegionQueries() {
+ addCollapsedFoldRegion(5, 7, "...");
+ FoldRegion[] regions = myModel.getAllFoldRegions();
+ assertEquals(1, regions.length);
+ FoldRegion region = regions[0];
+ assertNotNull(region);
+
+ assertFalse(myModel.isOffsetCollapsed(4));
+ assertTrue(myModel.isOffsetCollapsed(5));
+ assertTrue(myModel.isOffsetCollapsed(6));
+ assertFalse(myModel.isOffsetCollapsed(7));
+ assertFalse(myModel.isOffsetCollapsed(8));
+
+ assertNull(myModel.getCollapsedRegionAtOffset(4));
+ assertSame(region, myModel.getCollapsedRegionAtOffset(5));
+ assertSame(region, myModel.getCollapsedRegionAtOffset(6));
+ assertNull(myModel.getCollapsedRegionAtOffset(7));
+ assertNull(myModel.getCollapsedRegionAtOffset(8));
+ }
+
+ public void testAdjacentRegions() {
+ addCollapsedFoldRegion(5, 7, "AA");
+ addCollapsedFoldRegion(7, 10, "BB");
+ FoldRegion[] regions = myModel.getAllFoldRegions();
+ assertEquals(2, regions.length);
+ FoldRegion region1 = regions[0];
+ assertNotNull(region1);
+ FoldRegion region2 = regions[1];
+ assertNotNull(region2);
+
+ assertFalse(myModel.isOffsetCollapsed(4));
+ assertTrue(myModel.isOffsetCollapsed(5));
+ assertTrue(myModel.isOffsetCollapsed(6));
+ assertTrue(myModel.isOffsetCollapsed(7));
+ assertTrue(myModel.isOffsetCollapsed(8));
+ assertFalse(myModel.isOffsetCollapsed(10));
+ assertFalse(myModel.isOffsetCollapsed(11));
+
+ assertNull(myModel.getCollapsedRegionAtOffset(4));
+ assertSame(region1, myModel.getCollapsedRegionAtOffset(5));
+ assertSame(region1, myModel.getCollapsedRegionAtOffset(6));
+ assertSame(region2, myModel.getCollapsedRegionAtOffset(7));
+ assertSame(region2, myModel.getCollapsedRegionAtOffset(8));
+ assertNull(myModel.getCollapsedRegionAtOffset(10));
+ assertNull(myModel.getCollapsedRegionAtOffset(11));
+ }
+
+ public void testTopLevel() {
+ FoldRegion region = addCollapsedFoldRegion(5, 15, "...");
+ addCollapsedFoldRegion(10, 12, "???");
+
+ FoldRegion[] topLevelRegions = myModel.fetchTopLevel();
+ assertArrayEquals(new FoldRegion[]{region}, topLevelRegions);
}
}