mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
cleanup invalid fold regions (fix console leaks, IDEA-124626)
This commit is contained in:
+24
-19
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.codeInsight.editorActions.moveUpDown;
|
||||
|
||||
import com.intellij.codeInsight.folding.CodeFoldingManager;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -44,7 +45,7 @@ class MoverWrapper {
|
||||
return myInfo;
|
||||
}
|
||||
|
||||
public final void move(Editor editor, final PsiFile file) {
|
||||
public final void move(final Editor editor, final PsiFile file) {
|
||||
assert myInfo.toMove2 != null;
|
||||
myMover.beforeMove(editor, myInfo, myIsDown);
|
||||
final Document document = editor.getDocument();
|
||||
@@ -91,19 +92,8 @@ class MoverWrapper {
|
||||
// Pointer for the fold region from method1 points to 'method2()' now and vice versa (check range markers processing on
|
||||
// document change for further information). I.e. information about fold regions statuses holds the data swapped for
|
||||
// 'method1' and 'method2'. Hence, we want to apply correct 'collapsed' status.
|
||||
FoldRegion topRegion = null;
|
||||
FoldRegion bottomRegion = null;
|
||||
for (FoldRegion foldRegion : editor.getFoldingModel().getAllFoldRegions()) {
|
||||
if (!foldRegion.isValid() || (!contains(myInfo.range1, foldRegion) && !contains(myInfo.range2, foldRegion))) {
|
||||
continue;
|
||||
}
|
||||
if (contains(myInfo.range1, foldRegion) && !contains(topRegion, foldRegion)) {
|
||||
topRegion = foldRegion;
|
||||
}
|
||||
else if (contains(myInfo.range2, foldRegion) && !contains(bottomRegion, foldRegion)) {
|
||||
bottomRegion = foldRegion;
|
||||
}
|
||||
}
|
||||
final FoldRegion topRegion = findTopLevelRegionInRange(editor, myInfo.range1);
|
||||
final FoldRegion bottomRegion = findTopLevelRegionInRange(editor, myInfo.range2);
|
||||
|
||||
document.insertString(myInfo.range1.getStartOffset(), textToInsert2);
|
||||
document.deleteString(myInfo.range1.getStartOffset()+textToInsert2.length(), myInfo.range1.getEndOffset());
|
||||
@@ -120,14 +110,19 @@ class MoverWrapper {
|
||||
|
||||
// Swap fold regions status if necessary.
|
||||
if (topRegion != null && bottomRegion != null) {
|
||||
final FoldRegion finalTopRegion = topRegion;
|
||||
final FoldRegion finalBottomRegion = bottomRegion;
|
||||
CodeFoldingManager.getInstance(project).updateFoldRegions(editor);
|
||||
editor.getFoldingModel().runBatchFoldingOperation(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean topExpanded = finalTopRegion.isExpanded();
|
||||
finalTopRegion.setExpanded(finalBottomRegion.isExpanded());
|
||||
finalBottomRegion.setExpanded(topExpanded);
|
||||
FoldRegion newTopRegion = findTopLevelRegionInRange(editor, myInfo.range1);
|
||||
if (newTopRegion != null) {
|
||||
newTopRegion.setExpanded(bottomRegion.isExpanded());
|
||||
}
|
||||
|
||||
FoldRegion newBottomRegion = findTopLevelRegionInRange(editor, myInfo.range2);
|
||||
if (newBottomRegion != null) {
|
||||
newBottomRegion.setExpanded(topRegion.isExpanded());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -148,6 +143,16 @@ class MoverWrapper {
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
}
|
||||
|
||||
private static FoldRegion findTopLevelRegionInRange(Editor editor, RangeMarker range) {
|
||||
FoldRegion result = null;
|
||||
for (FoldRegion foldRegion : editor.getFoldingModel().getAllFoldRegions()) {
|
||||
if (foldRegion.isValid() && contains(range, foldRegion) && !contains(result, foldRegion)) {
|
||||
result = foldRegion;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to check if text range defined by the given range marker completely contains text range of the given fold region.
|
||||
*
|
||||
|
||||
@@ -80,12 +80,15 @@ abstract class FoldRegionsTree {
|
||||
void rebuild() {
|
||||
ArrayList<FoldRegion> topLevels = new ArrayList<FoldRegion>(myRegions.size() / 2);
|
||||
ArrayList<FoldRegion> visible = new ArrayList<FoldRegion>(myRegions.size());
|
||||
ArrayList<FoldRegion> allValid = new ArrayList<FoldRegion>(myRegions.size());
|
||||
FoldRegion[] regions = toFoldArray(myRegions);
|
||||
FoldRegion currentCollapsed = null;
|
||||
for (FoldRegion region : regions) {
|
||||
if (!region.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
allValid.add(region);
|
||||
|
||||
if (currentCollapsed == null || !contains(currentCollapsed, region)) {
|
||||
visible.add(region);
|
||||
@@ -99,6 +102,10 @@ abstract class FoldRegionsTree {
|
||||
}
|
||||
}
|
||||
|
||||
if (allValid.size() < myRegions.size()) {
|
||||
myRegions = allValid;
|
||||
}
|
||||
|
||||
myCachedTopLevelRegions = toFoldArray(topLevels);
|
||||
myCachedVisible = toFoldArray(visible);
|
||||
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
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.testFramework.PlatformTestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class FoldingTest extends LightPlatformTestCase {
|
||||
|
||||
static {
|
||||
PlatformTestCase.autodetectPlatformPrefix();
|
||||
}
|
||||
|
||||
public void testStressFoldingFromZeroOffset() throws Exception {
|
||||
for (int len = 2; len < 25; len++) {
|
||||
stress(len);
|
||||
@@ -68,6 +75,32 @@ public class FoldingTest extends LightPlatformTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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!'" +
|
||||
|
||||
Reference in New Issue
Block a user