EA-27384 - IOOBE: EditorImpl.calcLogicalLineNumber

This commit is contained in:
Denis Zhdanov
2011-05-04 12:42:24 +04:00
parent 3bc5070c66
commit 88f75a17dc
2 changed files with 71 additions and 31 deletions
@@ -64,8 +64,18 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
private final LogicalToVisualTask myLogicalToVisualTask = new LogicalToVisualTask();
private final FoldProcessingEndTask myFoldProcessingEndTask = new FoldProcessingEndTask();
private final List<DocumentListener> myDocumentListeners = new ArrayList<DocumentListener>();
private final List<FoldingListener> myFoldListeners = new ArrayList<FoldingListener>();
private final List<DocumentListener> myDocumentListeners = new ArrayList<DocumentListener>();
private final List<FoldingListener> myFoldListeners = new ArrayList<FoldingListener>();
/**
* There is a possible case that particular activity performs batch fold regions operations (addition, removal etc).
* We don't want to process them at the same time we get notifications about that because there is a big chance that
* we see inconsistent state (e.g. there was a problem with {@link FoldingModel#getCollapsedRegionAtOffset(int)} because that
* method uses caching internally and cached data becomes inconsistent if, for example, the top region is removed).
* <p/>
* So, our strategy is to collect information about changed fold regions and process it only when batch folding processing ends.
*/
private final List<FoldRegion> myDeferredFoldRegions = new ArrayList<FoldRegion>();
private final SoftWrapFoldBasedApplianceStrategy myFoldBasedApplianceStrategy;
private final CachingSoftWrapDataMapper myDataMapper;
@@ -170,6 +180,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
myUseSoftWraps = settings.isUseSoftWraps();
if (myUseSoftWraps && (!softWrapsUsedBefore || settings.getAdditionalColumnsCount() > 0)) {
myApplianceManager.reset();
myDeferredFoldRegions.clear();
myAdditionalColumnsCount = settings.getAdditionalColumnsCount();
settings.setAdditionalColumnsCount(0);
}
@@ -413,28 +424,12 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
if (myDirty) {
myApplianceManager.reset();
myDeferredFoldRegions.clear();
myDirty = false;
}
myApplianceManager.recalculateIfNecessary();
return true;
//
//Rectangle visibleArea = myEditor.getScrollingModel().getVisibleArea();
//if (visibleArea.width <= 0) {
// // We don't know visible area width, hence, can't calculate soft wraps positions.
// return false;
//}
//
//myActive++;
//try {
// LogicalPosition logicalPosition = myEditor.xyToLogicalPosition(visibleArea.getLocation());
// int offset = myEditor.logicalPositionToOffset(logicalPosition);
// myApplianceManager.registerSoftWrapIfNecessary(visibleArea, offset);
// return true;
//}
//finally {
// myActive--;
//}
}
/**
@@ -573,18 +568,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
return;
}
// There is a possible case that given fold region is contained inside another collapsed fold region. We don't want to process
// such nested region then.
FoldRegion outerRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(region.getStartOffset());
if (outerRegion != null && outerRegion != region && outerRegion.getStartOffset() <= region.getStartOffset()
&& outerRegion.getEndOffset() >= region.getEndOffset())
{
return;
}
for (FoldingListener listener : myFoldListeners) {
listener.onFoldRegionStateChange(region);
}
myDeferredFoldRegions.add(region);
}
@Override
@@ -608,6 +592,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
myDataMapper.release();
myApplianceManager.release();
myStorage.removeAll();
myDeferredFoldRegions.clear();
}
public SoftWrapApplianceManager getApplianceManager() {
@@ -742,6 +727,27 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
if (!softWrapAware) {
return;
}
try {
for (FoldRegion region : myDeferredFoldRegions) {
// There is a possible case that given fold region is contained inside another collapsed fold region. We don't want to process
// such nested region then.
FoldRegion outerRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(region.getStartOffset());
if (outerRegion != null && outerRegion != region && outerRegion.getStartOffset() <= region.getStartOffset()
&& outerRegion.getEndOffset() >= region.getEndOffset())
{
continue;
}
for (FoldingListener listener : myFoldListeners) {
listener.onFoldRegionStateChange(region);
}
}
}
finally {
myDeferredFoldRegions.clear();
}
for (FoldingListener listener : myFoldListeners) {
listener.onFoldProcessingEnd();
}
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.editor.impl.softwrap.mapping;
import com.intellij.codeInsight.folding.CodeFoldingManager;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.SoftWrapModelEx;
import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest;
@@ -703,6 +704,39 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
assertEquals(new VisualPosition(visLine, 0), caretModel.getVisualPosition());
}
public void testFoldRegionsUpdate() throws IOException {
String text =
"import java.util.List;\n" +
"import java.util.ArrayList;\n" +
"\n" +
"class Test {\n" +
"}";
init(300, text);
final int foldStartOffset = "import".length() + 1;
int foldEndOffset = text.indexOf("class") - 2;
addCollapsedFoldRegion(foldStartOffset, foldEndOffset, "...");
// Simulate addition of the new import that modifies existing fold region.
myEditor.getDocument().insertString(foldEndOffset, "\nimport java.util.Date;\n");
final FoldingModel foldingModel = myEditor.getFoldingModel();
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
FoldRegion oldFoldRegion = getFoldRegion(foldStartOffset);
assertNotNull(oldFoldRegion);
foldingModel.removeFoldRegion(oldFoldRegion);
int newFoldEndOffset = myEditor.getDocument().getText().indexOf("class") - 2;
FoldRegion newFoldRegion = foldingModel.addFoldRegion(foldStartOffset, newFoldEndOffset, "...");
assertNotNull(newFoldRegion);
newFoldRegion.setExpanded(false);
}
});
CodeFoldingManager.getInstance(getProject()).updateFoldRegions(myEditor);
assertEquals(new VisualPosition(2, 0), myEditor.logicalToVisualPosition(new LogicalPosition(5, 0)));
}
private void init(final int visibleWidth, String fileText) throws IOException {
init(fileText);
myEditor.getSettings().setUseSoftWraps(true);