one more correction for a folding model fix (IDEA-177458)

also make EditorStressTest validate folding model's internal state
This commit is contained in:
Dmitry Batrak
2017-08-15 17:49:21 +03:00
parent fc3fc3210a
commit f4136fc721
3 changed files with 63 additions and 7 deletions
@@ -37,7 +37,7 @@ abstract class FoldRegionsTree {
private static final Comparator<FoldRegion> BY_END_OFFSET = Comparator.comparingInt(RangeMarker::getEndOffset);
private static final Comparator<? super FoldRegion> BY_END_OFFSET_REVERSE = Collections.reverseOrder(BY_END_OFFSET);
private static final TObjectHashingStrategy<FoldRegion> OFFSET_BASED_HASHING_STRATEGY = new TObjectHashingStrategy<FoldRegion>() {
static final TObjectHashingStrategy<FoldRegion> OFFSET_BASED_HASHING_STRATEGY = new TObjectHashingStrategy<FoldRegion>() {
@Override
public int computeHashCode(FoldRegion o) {
return o.getStartOffset() * 31 + o.getEndOffset();
@@ -77,13 +77,14 @@ abstract class FoldRegionsTree {
public boolean process(int offset, @NotNull FoldRegionImpl region, boolean atStart, @NotNull Collection<FoldRegionImpl> overlapping) {
if (atStart) {
if (sameRange(region, lastRegion)) {
if (region.getUserData(VISIBLE) == null) {
if (region.getUserData(VISIBLE) == null || lastRegion.getUserData(VISIBLE) != null && region.isExpanded()) {
duplicatesToKill.add(region);
return true;
}
else {
duplicatesToKill.add(lastRegion);
if (!visible.isEmpty() && lastRegion == visible.get(visible.size() - 1)) removeFromVisible(visible.size() - 1);
if (lastRegion == lastCollapsedRegion) lastCollapsedRegion = null;
}
}
lastRegion = region;
@@ -34,12 +34,13 @@ import com.intellij.openapi.util.ModificationTracker;
import com.intellij.util.DocumentUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.awt.*;
import java.util.Arrays;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
@@ -622,10 +623,57 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedInternalDocu
@TestOnly
void validateState() {
for (FoldRegion region : getAllFoldRegions()) {
LOG.assertTrue (!region.isValid() ||
!DocumentUtil.isInsideSurrogatePair(myEditor.getDocument(), region.getStartOffset()) &&
!DocumentUtil.isInsideSurrogatePair(myEditor.getDocument(), region.getEndOffset()));
if (myEditor.getDocument().isInBulkUpdate()) return;
FoldRegion[] allFoldRegions = getAllFoldRegions();
boolean[] invisibleRegions = new boolean[allFoldRegions.length];
for (int i = 0; i < allFoldRegions.length; i++) {
FoldRegion r1 = allFoldRegions[i];
LOG.assertTrue(r1.isValid() &&
!DocumentUtil.isInsideSurrogatePair(myEditor.getDocument(), r1.getStartOffset()) &&
!DocumentUtil.isInsideSurrogatePair(myEditor.getDocument(), r1.getEndOffset()),
"Invalid region");
for (int j = i + 1; j < allFoldRegions.length; j++) {
FoldRegion r2 = allFoldRegions[j];
int r1s = r1.getStartOffset();
int r1e = r1.getEndOffset();
int r2s = r2.getStartOffset();
int r2e = r2.getEndOffset();
LOG.assertTrue(r1s < r2s && (r1e <= r2s || r1e >= r2e) ||
r1s == r2s && r1e != r2e ||
r1s > r2s && r1s < r2e && r1e <= r2e ||
r1s >= r2e,
"Disallowed relative position of regions");
if (!r1.isExpanded() && r1s <= r2s && r1e >= r2e) invisibleRegions[j] = true;
if (!r2.isExpanded() && r2s <= r1s && r2e >= r1e) invisibleRegions[i] = true;
}
}
Set<FoldRegion> visibleRegions = new THashSet<>(FoldRegionsTree.OFFSET_BASED_HASHING_STRATEGY);
List<FoldRegion> topLevelRegions = new ArrayList<>();
for (int i = 0; i < allFoldRegions.length; i++) {
if (!invisibleRegions[i]) {
FoldRegion region = allFoldRegions[i];
LOG.assertTrue(visibleRegions.add(region), "Duplicate visible regions");
if (!region.isExpanded()) topLevelRegions.add(region);
}
}
Collections.sort(topLevelRegions, Comparator.comparingInt(r -> r.getStartOffset()));
FoldRegion[] actualVisibles = fetchVisible();
if (actualVisibles != null) {
for (FoldRegion r : actualVisibles) {
LOG.assertTrue(visibleRegions.remove(r), "Unexpected visible region");
}
LOG.assertTrue(visibleRegions.isEmpty(), "Missing visible region");
}
FoldRegion[] actualTopLevels = fetchTopLevel();
if (actualTopLevels != null) {
LOG.assertTrue(actualTopLevels.length == topLevelRegions.size(), "Wrong number of top-level regions");
for (int i = 0; i < actualTopLevels.length; i++) {
LOG.assertTrue(FoldRegionsTree.OFFSET_BASED_HASHING_STRATEGY.equals(actualTopLevels[i], topLevelRegions.get(i)),
"Unexpected top-level region");
}
}
}
@@ -350,4 +350,11 @@ public class FoldingTest extends AbstractEditorTest {
addCollapsedFoldRegion(11, 12, "innermost");
Assert.assertArrayEquals(new FoldRegion[]{inner}, myModel.fetchTopLevel());
}
public void testIdenticalRegionsOtherCase() {
FoldRegion inner = addCollapsedFoldRegion(10, 15, "inner");
addFoldRegion(10, 20, "outer");
WriteCommandAction.runWriteCommandAction(ourProject, () -> myEditor.getDocument().deleteString(15, 20));
Assert.assertArrayEquals(new FoldRegion[]{inner}, myModel.fetchTopLevel());
}
}