diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java index 79cf1924369c..991248350268 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java @@ -32,8 +32,8 @@ public class EditorDocumentPriorities { */ public static final int RANGE_MARKER = 40; - public static final int SOFT_WRAP_MODEL = 60; - public static final int FOLD_MODEL = 80; + public static final int FOLD_MODEL = 60; + public static final int SOFT_WRAP_MODEL = 80; public static final int LEXER_EDITOR = 100; public static final int CARET_MODEL = 120; public static final int SELECTION_MODEL = 140; 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 e2921401f901..f46d773a9f57 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 @@ -167,9 +167,9 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList final FoldingGroup group = region.getGroup(); if (group != null) { myGroups.putValue(group, region); - for (FoldingListener listener : myListeners) { - listener.onFoldRegionStateChange(region); - } + } + for (FoldingListener listener : myListeners) { + listener.onFoldRegionStateChange(region); } return true; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index af88b5231bd8..a2a1975a9759 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -76,6 +76,17 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi private int myActive; private boolean myUseSoftWraps; + /** + * Soft wraps need to be kept up-to-date on all editor modification (changing text, adding/removing/expanding/collapsing fold + * regions etc). Hence, we need to react to all types of target changes. However, soft wraps processing uses various information + * provided by editor and there is a possible case that that information is inconsistent during update time (e.g. fold model + * advances fold region offsets when end-user types before it, hence, fold regions data is inconsistent between the moment + * when text changes are applied to the document and fold data is actually updated). + *

+ * Current field serves as a flag that indicates if all preliminary actions necessary for successful soft wraps processing is done. + */ + private boolean myUpdateInProgress; + public SoftWrapModelImpl(@NotNull EditorEx editor) { this(editor, new SoftWrapsStorage(), new CompositeSoftWrapPainter(editor)); } @@ -271,7 +282,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @NotNull @Override public LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visual) { - if (!prepareToMapping()) { + if (myUpdateInProgress || !prepareToMapping()) { return myEditor.visualToLogicalPosition(visual, false); } myActive++; @@ -287,7 +298,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @NotNull @Override public LogicalPosition offsetToLogicalPosition(int offset) { - if (!prepareToMapping()) { + if (myUpdateInProgress || !prepareToMapping()) { return myEditor.offsetToLogicalPosition(offset, false); } myActive++; @@ -302,7 +313,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @NotNull public LogicalPosition adjustLogicalPosition(LogicalPosition defaultLogical, int offset) { - if (!prepareToMapping()) { + if (myUpdateInProgress || !prepareToMapping()) { return defaultLogical; } @@ -318,7 +329,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @NotNull public VisualPosition adjustVisualPosition(@NotNull LogicalPosition logical, @NotNull VisualPosition defaultVisual) { - if (!prepareToMapping()) { + if (myUpdateInProgress || !prepareToMapping()) { return defaultVisual; } @@ -477,6 +488,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public void beforeDocumentChange(DocumentEvent event) { + myUpdateInProgress = true; if (!isSoftWrappingEnabled()) { return; } @@ -487,6 +499,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public void documentChanged(DocumentEvent event) { + myUpdateInProgress = false; if (!isSoftWrappingEnabled()) { return; } @@ -497,6 +510,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public void onFoldRegionStateChange(@NotNull FoldRegion region) { + myUpdateInProgress = true; if (!isSoftWrappingEnabled() || !region.isValid()) { return; } @@ -507,6 +521,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public void onFoldProcessingEnd() { + myUpdateInProgress = false; if (!isSoftWrappingEnabled()) { return; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 6c6da2a5a619..518b073d1c14 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -199,7 +199,7 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen processNonFoldToken(); } else { - boolean continueProcessing = processCollapsedFoldRegion(currentFold, event); + boolean continueProcessing = processCollapsedFoldRegion(currentFold); if (!continueProcessing) { return false; } @@ -224,11 +224,10 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen * Encapsulates logic of processing given collapsed fold region. * * @param foldRegion target collapsed fold region to process - * @param event change event that triggered the processing * @return true if processing should be continued; false otherwise */ - private boolean processCollapsedFoldRegion(FoldRegion foldRegion, IncrementalCacheUpdateEvent event) { - if (processOutOfDateFoldRegion(foldRegion, event)) { + private boolean processCollapsedFoldRegion(FoldRegion foldRegion) { + if (processOutOfDateFoldRegion(foldRegion)) { return false; } @@ -298,11 +297,10 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen * This method encapsulates logic for checking and reacting on such a situation. * * @param foldRegion fold region that may be out-of-date - * @param event change event that triggered the processing * @return true if given fold region is really out-of-date and processing should be stopped; * false otherwise; */ - private boolean processOutOfDateFoldRegion(FoldRegion foldRegion, IncrementalCacheUpdateEvent event) { + private boolean processOutOfDateFoldRegion(FoldRegion foldRegion) { Document document = myEditor.getDocument(); @@ -310,17 +308,11 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen // case that offsets of the trailing fold regions should be updated as well. IncrementalCacheUpdateEvent newEvent = new IncrementalCacheUpdateEvent(document); - // We assume here that fold model is processed after soft wrap (as it needs to perform document dimensions mapping). - // So, there is a possible case that user performed modifications at particular fold region but fold model is not updated yet - // and IterationState returns valid fold region. Hence, we introduce a dedicated check here. - if (!foldRegion.isValid() || (event.getExactOffsetsDiff() != 0 && foldRegion.getStartOffset() < event.getOldExactEndOffset() - && foldRegion.getEndOffset() > event.getOldExactStartOffset()) || myContext.tokenStartOffset != foldRegion.getStartOffset()) - { + if (!foldRegion.isValid() || myContext.tokenStartOffset != foldRegion.getStartOffset()) { myEventsStorage.add(document, newEvent); return true; } - if (foldRegion.getEndOffset() <= document.getTextLength()) { return false; }