From c57b73d20cf095881cada01981ca97dcb7d62369 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 19 Dec 2014 14:42:22 +0300 Subject: [PATCH] reduce visibility to prevent subclassing of RangeMarkerImpl which can break tree invariants --- .../impl/PersistentRangeMarkerUtil.java | 10 +- .../injected/editor/FoldingModelWindow.java | 11 +- .../injected/editor/FoldingRegionWindow.java | 24 +- .../injected/editor/RangeMarkerWindow.java | 11 +- .../incrementalMerge/DiffRangeMarker.java | 106 +++++++-- .../impl/incrementalMerge/SimpleChange.java | 17 +- .../openapi/editor/impl/CaretImpl.java | 210 ++++++++---------- .../openapi/editor/impl/FoldRegionImpl.java | 7 +- 8 files changed, 226 insertions(+), 170 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java index 2e78c2cc067b..a5bc62c1d2e7 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 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. @@ -23,11 +23,7 @@ import org.jetbrains.annotations.NotNull; * @author Denis Zhdanov * @since 12/27/10 4:26 PM */ -public class PersistentRangeMarkerUtil { - - private PersistentRangeMarkerUtil() { - } - +class PersistentRangeMarkerUtil { /** * Answers if document region identified by the given range marker should be translated via diff algorithm on document change * identified by the given event. @@ -37,7 +33,7 @@ public class PersistentRangeMarkerUtil { * @return true if target document range referenced by the given range marker should be translated via * diff algorithm; false otherwise */ - public static boolean shouldTranslateViaDiff(@NotNull DocumentEventImpl e, @NotNull RangeMarker rangeMarker) { + static boolean shouldTranslateViaDiff(@NotNull DocumentEventImpl e, @NotNull RangeMarker rangeMarker) { if (e.isWholeTextReplaced()) { // Perform translation if the whole text is replaced. return true; diff --git a/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java index 3c839f208312..0fe1a2f2ef4a 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java @@ -21,7 +21,6 @@ import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.editor.ex.FoldingListener; import com.intellij.openapi.editor.ex.FoldingModelEx; -import com.intellij.openapi.editor.impl.FoldRegionImpl; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; @@ -35,12 +34,12 @@ import java.util.List; /** * @author cdr */ -public class FoldingModelWindow implements FoldingModelEx{ +class FoldingModelWindow implements FoldingModelEx{ private final FoldingModelEx myDelegate; private final DocumentWindow myDocumentWindow; private final EditorWindow myEditorWindow; - public FoldingModelWindow(@NotNull FoldingModelEx delegate, @NotNull DocumentWindow documentWindow, @NotNull EditorWindow editorWindow) { + FoldingModelWindow(@NotNull FoldingModelEx delegate, @NotNull DocumentWindow documentWindow, @NotNull EditorWindow editorWindow) { myDelegate = delegate; myDocumentWindow = documentWindow; myEditorWindow = editorWindow; @@ -82,12 +81,12 @@ public class FoldingModelWindow implements FoldingModelEx{ @Override public boolean addFoldRegion(@NotNull final FoldRegion region) { - return myDelegate.addFoldRegion(((FoldingRegionWindow)region).getDelegate()); + return myDelegate.addFoldRegion((FoldRegion)((FoldingRegionWindow)region).getDelegate()); } @Override public void removeFoldRegion(@NotNull FoldRegion region) { - myDelegate.removeFoldRegion(((FoldingRegionWindow)region).getDelegate()); + myDelegate.removeFoldRegion((FoldRegion)((FoldingRegionWindow)region).getDelegate()); } @Override @@ -172,7 +171,7 @@ public class FoldingModelWindow implements FoldingModelEx{ FoldRegion hostRegion = myDelegate.createFoldRegion(hostRange.getStartOffset(), hostRange.getEndOffset(), placeholder, group, neverExpands); int startShift = Math.max(0, myDocumentWindow.hostToInjected(hostRange.getStartOffset()) - startOffset); int endShift = Math.max(0, endOffset - myDocumentWindow.hostToInjected(hostRange.getEndOffset()) - startShift); - FoldingRegionWindow window = new FoldingRegionWindow(myDocumentWindow, myEditorWindow, (FoldRegionImpl)hostRegion, startShift, endShift); + FoldingRegionWindow window = new FoldingRegionWindow(myDocumentWindow, myEditorWindow, hostRegion, startShift, endShift); hostRegion.putUserData(FOLD_REGION_WINDOW, window); return window; } diff --git a/platform/lang-impl/src/com/intellij/injected/editor/FoldingRegionWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/FoldingRegionWindow.java index 74b4bc32e1ec..8a382f4c018a 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/FoldingRegionWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/FoldingRegionWindow.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. @@ -18,24 +18,24 @@ package com.intellij.injected.editor; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.FoldingGroup; -import com.intellij.openapi.editor.impl.FoldRegionImpl; +import com.intellij.openapi.editor.ex.RangeMarkerEx; import org.jetbrains.annotations.NotNull; /** * User: cdr */ -public class FoldingRegionWindow extends RangeMarkerWindow implements FoldRegion { +class FoldingRegionWindow extends RangeMarkerWindow implements FoldRegion { private final EditorWindow myEditorWindow; - private final FoldRegionImpl myHostRegion; + private final FoldRegion myHostRegion; - public FoldingRegionWindow(@NotNull DocumentWindow documentWindow, - @NotNull EditorWindow editorWindow, - @NotNull FoldRegionImpl hostRegion, - int startShift, - int endShift) + FoldingRegionWindow(@NotNull DocumentWindow documentWindow, + @NotNull EditorWindow editorWindow, + @NotNull FoldRegion hostRegion, + int startShift, + int endShift) { - super(documentWindow, hostRegion, startShift, endShift); + super(documentWindow, (RangeMarkerEx)hostRegion, startShift, endShift); myEditorWindow = editorWindow; myHostRegion = hostRegion; } @@ -72,7 +72,7 @@ public class FoldingRegionWindow extends RangeMarkerWindow implements FoldRegion } @Override - public FoldRegionImpl getDelegate() { - return myHostRegion; + public RangeMarkerEx getDelegate() { + return (RangeMarkerEx)myHostRegion; } } diff --git a/platform/lang-impl/src/com/intellij/injected/editor/RangeMarkerWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/RangeMarkerWindow.java index fbe0d3070009..59dacc78eba7 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/RangeMarkerWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/RangeMarkerWindow.java @@ -29,12 +29,11 @@ import com.intellij.openapi.util.Key; import com.intellij.psi.PsiLanguageInjectionHost; import org.jetbrains.annotations.NotNull; -public class RangeMarkerWindow implements RangeMarkerEx { - +class RangeMarkerWindow implements RangeMarkerEx { private final DocumentWindow myDocumentWindow; - private final RangeMarkerEx myHostMarker; - private final int myStartShift; - private final int myEndShift; + private final RangeMarkerEx myHostMarker; + private final int myStartShift; + private final int myEndShift; /** * Creates new RangeMarkerWindow object with the given data. @@ -51,7 +50,7 @@ public class RangeMarkerWindow implements RangeMarkerEx { * @param endShift similar to the 'startShift' argument but specifies difference between the target injected host end offset * and end offset of the given host range marker at the injected text */ - public RangeMarkerWindow(@NotNull DocumentWindow documentWindow, RangeMarkerEx hostMarker, int startShift, int endShift) { + RangeMarkerWindow(@NotNull DocumentWindow documentWindow, RangeMarkerEx hostMarker, int startShift, int endShift) { myDocumentWindow = documentWindow; myHostMarker = hostMarker; myStartShift = startShift; diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/DiffRangeMarker.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/DiffRangeMarker.java index 53d53505b123..05b4a26f08e8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/DiffRangeMarker.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/DiffRangeMarker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -17,30 +17,40 @@ package com.intellij.openapi.diff.impl.incrementalMerge; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.ex.DocumentEx; -import com.intellij.openapi.editor.impl.RangeMarkerImpl; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -class DiffRangeMarker extends RangeMarkerImpl { +class DiffRangeMarker implements RangeMarker { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.DiffRangeMarker"); + private final RangeMarker myRangeMarker; private RangeInvalidListener myListener; - DiffRangeMarker(@NotNull DocumentEx document, @NotNull TextRange range, RangeInvalidListener listener) { - super(document, range.getStartOffset(), range.getEndOffset(),true); + DiffRangeMarker(@NotNull Document document, @NotNull TextRange range, RangeInvalidListener listener) { + myRangeMarker = document.createRangeMarker(range.getStartOffset(), range.getEndOffset()); myListener = listener; - if (myListener != null) InvalidRangeDispatcher.addClient(document); - } - - @Override - protected void changedUpdateImpl(DocumentEvent e) { - super.changedUpdateImpl(e); - if (!isValid() && myListener != null) InvalidRangeDispatcher.notify(e.getDocument(), myListener); + if (listener != null) { + final InvalidRangeDispatcher notifier = InvalidRangeDispatcher.addClient(document); + document.addDocumentListener(new DocumentAdapter() { + @Override + public void beforeDocumentChange(DocumentEvent e) { + if (myListener != null) { + notifier.notify(new RangeInvalidListener() { + @Override + public void onRangeInvalidated() { + if (!isValid() && myListener != null) myListener.onRangeInvalidated(); + } + }); + } + } + }); + } } public void removeListener(RangeInvalidListener listener) { @@ -49,7 +59,7 @@ class DiffRangeMarker extends RangeMarkerImpl { InvalidRangeDispatcher.removeClient(getDocument()); } - public interface RangeInvalidListener { + interface RangeInvalidListener { void onRangeInvalidated(); } @@ -58,6 +68,7 @@ class DiffRangeMarker extends RangeMarkerImpl { private final ArrayList myDeferedNotifications = new ArrayList(); private int myClientCount = 0; + @Override public void documentChanged(DocumentEvent e) { if (myDeferedNotifications.isEmpty()) return; RangeInvalidListener[] notifications = myDeferedNotifications.toArray(new RangeInvalidListener[myDeferedNotifications.size()]); @@ -67,12 +78,11 @@ class DiffRangeMarker extends RangeMarkerImpl { } } - public static void notify(Document document, RangeInvalidListener listener) { - InvalidRangeDispatcher notifier = document.getUserData(KEY); - notifier.myDeferedNotifications.add(listener); + public void notify(@NotNull RangeInvalidListener listener) { + myDeferedNotifications.add(listener); } - public static void addClient(@NotNull Document document) { + private static InvalidRangeDispatcher addClient(@NotNull Document document) { InvalidRangeDispatcher notifier = document.getUserData(KEY); if (notifier == null) { notifier = new InvalidRangeDispatcher(); @@ -80,6 +90,7 @@ class DiffRangeMarker extends RangeMarkerImpl { document.addDocumentListener(notifier); } notifier.myClientCount++; + return notifier; } private static void removeClient(Document document) { @@ -96,4 +107,63 @@ class DiffRangeMarker extends RangeMarkerImpl { } } } + + /// delegates + + @Override + @NotNull + public Document getDocument() { + return myRangeMarker.getDocument(); + } + + @Override + public int getStartOffset() { + return myRangeMarker.getStartOffset(); + } + + @Override + public int getEndOffset() { + return myRangeMarker.getEndOffset(); + } + + @Override + public boolean isValid() { + return myRangeMarker.isValid(); + } + + @Override + public void setGreedyToLeft(boolean greedy) { + myRangeMarker.setGreedyToLeft(greedy); + } + + @Override + public void setGreedyToRight(boolean greedy) { + myRangeMarker.setGreedyToRight(greedy); + } + + @Override + public boolean isGreedyToRight() { + return myRangeMarker.isGreedyToRight(); + } + + @Override + public boolean isGreedyToLeft() { + return myRangeMarker.isGreedyToLeft(); + } + + @Override + public void dispose() { + myRangeMarker.dispose(); + } + + @Override + @Nullable + public T getUserData(@NotNull Key key) { + return myRangeMarker.getUserData(key); + } + + @Override + public void putUserData(@NotNull Key key, @Nullable T value) { + myRangeMarker.putUserData(key, value); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/SimpleChange.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/SimpleChange.java index 115db170f617..254b94bc8bec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/SimpleChange.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/SimpleChange.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -18,7 +18,6 @@ package com.intellij.openapi.diff.impl.incrementalMerge; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; -import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; @@ -28,15 +27,16 @@ class SimpleChange extends Change implements DiffRangeMarker.RangeInvalidListene private final SimpleChangeSide[] mySides; private final ChangeList myChangeList; - public SimpleChange(@NotNull ChangeType type, @NotNull TextRange range1, @NotNull TextRange range2, @NotNull ChangeList changeList) { + SimpleChange(@NotNull ChangeType type, @NotNull TextRange range1, @NotNull TextRange range2, @NotNull ChangeList changeList) { mySides = new SimpleChangeSide[]{ createSide(changeList, range1, FragmentSide.SIDE1), createSide(changeList, range2, FragmentSide.SIDE2)}; myType = type; myChangeList = changeList; } + @NotNull private SimpleChangeSide createSide(@NotNull ChangeList changeList, @NotNull TextRange range1, @NotNull FragmentSide side) { - return new SimpleChangeSide(side, new DiffRangeMarker((DocumentEx)changeList.getDocument(side), range1, this)); + return new SimpleChangeSide(side, new DiffRangeMarker(changeList.getDocument(side), range1, this)); } /** @@ -55,19 +55,23 @@ class SimpleChange extends Change implements DiffRangeMarker.RangeInvalidListene } } + @Override protected void removeFromList() { myChangeList.remove(this); } + @Override @NotNull public ChangeSide getChangeSide(@NotNull FragmentSide side) { return mySides[side.getIndex()]; } + @Override public ChangeType getType() { return myType; } + @Override public ChangeList getChangeList() { return myChangeList; } @@ -83,6 +87,7 @@ class SimpleChange extends Change implements DiffRangeMarker.RangeInvalidListene myChangeList.apply(this); } + @Override public void onRemovedFromList() { for (int i = 0; i < mySides.length; i++) { SimpleChangeSide side = mySides[i]; @@ -92,16 +97,18 @@ class SimpleChange extends Change implements DiffRangeMarker.RangeInvalidListene } } + @Override public boolean isValid() { LOG.assertTrue((mySides[0] == null) == (mySides[1] == null)); return mySides[0] != null; } + @Override public void onRangeInvalidated() { myChangeList.remove(this); } - public static Change fromRanges(@NotNull TextRange baseRange, @NotNull TextRange versionRange, @NotNull ChangeList changeList) { + static Change fromRanges(@NotNull TextRange baseRange, @NotNull TextRange versionRange, @NotNull ChangeList changeList) { ChangeType type = ChangeType.fromRanges(baseRange, versionRange); return new SimpleChange(type, baseRange, versionRange, changeList); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java index b66cd66eaf77..f3fdfd3b99d0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java @@ -95,7 +95,11 @@ public class CaretImpl extends UserDataHolderBase implements Caret { */ private int myDesiredX = -1; - private volatile MyRangeMarker mySelectionMarker; + private volatile RangeMarker mySelectionMarker; + private volatile VisualPosition myRangeMarkerStartPosition; + private volatile VisualPosition myRangeMarkerEndPosition; + private volatile boolean myRangeMarkerEndPositionIsLead; + private int startBefore; private int endBefore; boolean myUnknownDirection; @@ -140,7 +144,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } public void beforeDocumentChange() { - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; if (marker != null && marker.isValid()) { startBefore = marker.getStartOffset(); endBefore = marker.getEndOffset(); @@ -148,7 +152,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } public void documentChanged() { - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; if (marker != null) { int endAfter; int startAfter; @@ -164,7 +168,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } else { startAfter = endAfter = getOffset(); - marker.release(); + marker.dispose(); myStartVirtualOffset = 0; myEndVirtualOffset = 0; mySelectionMarker = null; @@ -189,6 +193,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { return; } myEditor.getCaretModel().doWithCaretMerging(new Runnable() { + @Override public void run() { final LogicalPosition logicalPosition = myEditor.offsetToLogicalPosition(offset); CaretEvent event = moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, null, false); @@ -203,12 +208,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret { int inverseOffset = myEditor.logicalPositionToOffset(logicalPosition); LogMessageEx.error( LOG, "caret moved to wrong offset. Please submit a dedicated ticket and attach current editor's text to it.", - String.format( - "Requested: offset=%d, logical position='%s' but actual: offset=%d, logical position='%s' (%s). %s%n" - + "interested text [%d;%d): '%s'%n debug trace: %s%nLogical position -> offset ('%s'->'%d')", - offset, logicalPosition, myOffset, myLogicalCaret, positionByOffsetAfterMove, myEditor.dumpState(), - textStart, textEnd, text, debugBuffer, logicalPosition, inverseOffset - ) + "Requested: offset=" + offset + ", logical position='" + logicalPosition + "' but actual: offset=" + + myOffset + ", logical position='" + myLogicalCaret + "' (" + positionByOffsetAfterMove + "). " + myEditor.dumpState() + + "\ninterested text [" + textStart + ";" + textEnd + "): '" + text + "'\n debug trace: " + debugBuffer + + "\nLogical position -> offset ('" + logicalPosition + "'->'" + inverseOffset + "')" ); } if (event != null) { @@ -251,6 +254,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { CopyPasteManager.getInstance().stopKillRings(); } myEditor.getCaretModel().doWithCaretMerging(new Runnable() { + @Override public void run() { SelectionModelImpl selectionModel = myEditor.getSelectionModel(); final int leadSelectionOffset = getLeadSelectionOffset(); @@ -431,6 +435,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { @Override public void moveToLogicalPosition(@NotNull final LogicalPosition pos) { myEditor.getCaretModel().doWithCaretMerging(new Runnable() { + @Override public void run() { moveToLogicalPosition(pos, false, null, true); } @@ -593,10 +598,9 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } } else { - LogMessageEx.error(LOG, "Invalid editor dimension mapping", String.format( - "Expected to map visual position '%s' to offset %d but got the following: -> logical position '%s'; -> offset %d. " - + "State: %s", visualPosition, myOffset, logicalPosition, tmpOffset, myEditor.dumpState() - )); + LogMessageEx.error(LOG, "Invalid editor dimension mapping", "Expected to map visual position '" + + visualPosition + "' to offset " + myOffset + " but got the following: -> logical position '" + + logicalPosition + "'; -> offset " + tmpOffset + ". State: " + myEditor.dumpState()); } } } @@ -651,6 +655,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { @Override public void moveToVisualPosition(@NotNull final VisualPosition pos) { myEditor.getCaretModel().doWithCaretMerging(new Runnable() { + @Override public void run() { moveToVisualPosition(pos, true); } @@ -767,7 +772,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { @Override public void dispose() { if (mySelectionMarker != null) { - mySelectionMarker.release(); + mySelectionMarker.dispose(); mySelectionMarker = null; } releaseBulkCaretMarker(); @@ -837,7 +842,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { /** * Recalculates caret visual position without changing its logical position (called when soft wraps are changing) */ - public void updateVisualPosition() { + void updateVisualPosition() { VerticalInfo oldInfo = myCaretInfo; LogicalPosition visUnawarePos = new LogicalPosition(myLogicalCaret.line, myLogicalCaret.column); setCurrentLogicalCaret(visUnawarePos); @@ -956,20 +961,20 @@ public class CaretImpl extends UserDataHolderBase implements Caret { return newOffset; } - CaretImpl cloneWithoutSelection() { + private CaretImpl cloneWithoutSelection() { CaretImpl clone = new CaretImpl(myEditor); - clone.myLogicalCaret = this.myLogicalCaret; - clone.myCaretInfo = this.myCaretInfo; - clone.myVisibleCaret = this.myVisibleCaret; - clone.myOffset = this.myOffset; - clone.myVirtualSpaceOffset = this.myVirtualSpaceOffset; - clone.myVisualLineStart = this.myVisualLineStart; - clone.myVisualLineEnd = this.myVisualLineEnd; - clone.savedBeforeBulkCaretMarker = this.savedBeforeBulkCaretMarker; - clone.mySkipChangeRequests = this.mySkipChangeRequests; - clone.myLastColumnNumber = this.myLastColumnNumber; - clone.myReportCaretMoves = this.myReportCaretMoves; - clone.myDesiredX = this.myDesiredX; + clone.myLogicalCaret = myLogicalCaret; + clone.myCaretInfo = myCaretInfo; + clone.myVisibleCaret = myVisibleCaret; + clone.myOffset = myOffset; + clone.myVirtualSpaceOffset = myVirtualSpaceOffset; + clone.myVisualLineStart = myVisualLineStart; + clone.myVisualLineEnd = myVisualLineEnd; + clone.savedBeforeBulkCaretMarker = savedBeforeBulkCaretMarker; + clone.mySkipChangeRequests = mySkipChangeRequests; + clone.myLastColumnNumber = myLastColumnNumber; + clone.myReportCaretMoves = myReportCaretMoves; + clone.myDesiredX = myDesiredX; clone.myDesiredSelectionStartColumn = -1; clone.myDesiredSelectionEndColumn = -1; return clone; @@ -981,8 +986,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret { assertIsDispatchThread(); int lineShift = above ? -1 : 1; final CaretImpl clone = cloneWithoutSelection(); - final int newSelectionStartOffset, newSelectionEndOffset, newSelectionStartColumn, newSelectionEndColumn; - final VisualPosition newSelectionStartPosition, newSelectionEndPosition; + final int newSelectionStartOffset; + final int newSelectionEndOffset; + final int newSelectionStartColumn; + final int newSelectionEndColumn; + final VisualPosition newSelectionStartPosition; + final VisualPosition newSelectionEndPosition; final boolean hasNewSelection; if (hasSelection() || myDesiredSelectionStartColumn >=0 || myDesiredSelectionEndColumn >= 0) { VisualPosition startPosition = getSelectionStartPosition(); @@ -1060,7 +1069,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { * @return information on whether current selection's direction in known * @see #setUnknownDirection(boolean) */ - public boolean isUnknownDirection() { + boolean isUnknownDirection() { return myUnknownDirection; } @@ -1076,9 +1085,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { * Note: when this method is called with 'true', subsequent calls are guaranteed to return 'true' * until selection is changed. 'Unknown direction' flag is automatically reset then. * - * @param unknownDirection */ - public void setUnknownDirection(boolean unknownDirection) { + void setUnknownDirection(boolean unknownDirection) { myUnknownDirection = unknownDirection; } @@ -1086,7 +1094,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { public int getSelectionStart() { validateContext(false); if (hasSelection()) { - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; if (marker != null) { return marker.getStartOffset(); } @@ -1100,7 +1108,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { validateContext(false); VisualPosition position; if (hasSelection() && mySelectionMarker != null) { - position = mySelectionMarker.getStartPosition(); + position = getRangeMarkerStartPosition(); if (position == null) { position = myEditor.offsetToVisualPosition(mySelectionMarker.getStartOffset()); } @@ -1118,7 +1126,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { public int getSelectionEnd() { validateContext(false); if (hasSelection()) { - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; if (marker != null) { return marker.getEndOffset(); } @@ -1132,7 +1140,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { validateContext(false); VisualPosition position; if (hasSelection() && mySelectionMarker != null) { - position = mySelectionMarker.getEndPosition(); + position = getRangeMarkerEndPosition(); if (position == null) { position = myEditor.offsetToVisualPosition(mySelectionMarker.getEndOffset()); } @@ -1149,7 +1157,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { @Override public boolean hasSelection() { validateContext(false); - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; return marker != null && marker.isValid() && (marker.getEndOffset() > marker.getStartOffset() || isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset); } @@ -1197,6 +1205,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { final boolean updateSystemSelection) { myEditor.getCaretModel().doWithCaretMerging(new Runnable() { + @Override public void run() { int startOffset = _startOffset; int endOffset = _endOffset; @@ -1255,24 +1264,24 @@ public class CaretImpl extends UserDataHolderBase implements Caret { oldSelectionStart = oldSelectionEnd = getOffset(); } - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; if (marker != null) { - marker.release(); + marker.dispose(); } - marker = new MyRangeMarker((DocumentEx)doc, startOffset, endOffset); + marker = doc.createRangeMarker(startOffset, endOffset); myStartVirtualOffset = 0; myEndVirtualOffset = 0; if (visualPositionAware) { if (endPosition.after(startPosition)) { - marker.setStartPosition(startPosition); - marker.setEndPosition(endPosition); - marker.setEndPositionIsLead(false); + setRangeMarkerStartPosition(startPosition); + setRangeMarkerEndPosition(endPosition); + setRangeMarkerEndPositionIsLead(false); } else { - marker.setStartPosition(endPosition); - marker.setEndPosition(startPosition); - marker.setEndPositionIsLead(true); + setRangeMarkerStartPosition(endPosition); + setRangeMarkerEndPosition(startPosition); + setRangeMarkerEndPositionIsLead(true); } if (isVirtualSelectionEnabled() && @@ -1314,15 +1323,16 @@ public class CaretImpl extends UserDataHolderBase implements Caret { return; } myEditor.getCaretModel().doWithCaretMerging(new Runnable() { + @Override public void run() { validateContext(true); myEditor.getSelectionModel().removeBlockSelection(); int caretOffset = getOffset(); - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; if (marker != null) { int startOffset = marker.getStartOffset(); int endOffset = marker.getEndOffset(); - marker.release(); + marker.dispose(); mySelectionMarker = null; myStartVirtualOffset = 0; myEndVirtualOffset = 0; @@ -1337,7 +1347,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { validateContext(false); int caretOffset = getOffset(); if (hasSelection()) { - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; if (marker != null) { int startOffset = marker.getStartOffset(); int endOffset = marker.getEndOffset(); @@ -1369,7 +1379,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { @NotNull @Override public VisualPosition getLeadSelectionPosition() { - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; VisualPosition caretPosition = getVisualPosition(); if (isVirtualSelectionEnabled() && !hasSelection()) { return caretPosition; @@ -1378,8 +1388,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { return caretPosition; } - if (marker.isEndPositionIsLead()) { - VisualPosition result = marker.getEndPosition(); + if (isRangeMarkerEndPositionIsLead()) { + VisualPosition result = getRangeMarkerEndPosition(); if (result == null) { return getSelectionEndPosition(); } @@ -1391,7 +1401,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } } else { - VisualPosition result = marker.getStartPosition(); + VisualPosition result = getRangeMarkerStartPosition(); if (result == null) { return getSelectionStartPosition(); } @@ -1408,6 +1418,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { public void selectLineAtCaret() { validateContext(true); myEditor.getCaretModel().doWithCaretMerging(new Runnable() { + @Override public void run() { SelectionModelImpl.doSelectLineAtCaret(myEditor); } @@ -1418,6 +1429,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { public void selectWordAtCaret(final boolean honorCamelWordsSettings) { validateContext(true); myEditor.getCaretModel().doWithCaretMerging(new Runnable() { + @Override public void run() { removeSelection(); final EditorSettings settings = myEditor.getSettings(); @@ -1481,7 +1493,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { boolean hasVirtualSelection() { validateContext(false); - MyRangeMarker marker = mySelectionMarker; + RangeMarker marker = mySelectionMarker; return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset; } @@ -1503,7 +1515,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { /** * Encapsulates information about target vertical range info - its 'y' coordinate and height in pixels. */ - public static class VerticalInfo { + private static class VerticalInfo { public final int y; public final int height; @@ -1513,68 +1525,40 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } } - private class MyRangeMarker extends RangeMarkerImpl { - private VisualPosition myStartPosition; - private VisualPosition myEndPosition; - private boolean myEndPositionIsLead; - private boolean myIsReleased; + @Nullable + private VisualPosition getRangeMarkerStartPosition() { + invalidateRangeMarkerVisualPositions(mySelectionMarker); + return myRangeMarkerStartPosition; + } - MyRangeMarker(DocumentEx document, int start, int end) { - super(document, start, end, true); - myIsReleased = false; - } + private void setRangeMarkerStartPosition(@NotNull VisualPosition startPosition) { + myRangeMarkerStartPosition = startPosition; + } - public void release() { - myIsReleased = true; - dispose(); - } + @Nullable + private VisualPosition getRangeMarkerEndPosition() { + invalidateRangeMarkerVisualPositions(mySelectionMarker); + return myRangeMarkerEndPosition; + } - @Nullable - public VisualPosition getStartPosition() { - invalidateVisualPositions(); - return myStartPosition; - } + void setRangeMarkerEndPosition(@NotNull VisualPosition endPosition) { + myRangeMarkerEndPosition = endPosition; + } - public void setStartPosition(@NotNull VisualPosition startPosition) { - myStartPosition = startPosition; - } + private boolean isRangeMarkerEndPositionIsLead() { + return myRangeMarkerEndPositionIsLead; + } - @Nullable - public VisualPosition getEndPosition() { - invalidateVisualPositions(); - return myEndPosition; - } + void setRangeMarkerEndPositionIsLead(boolean endPositionIsLead) { + myRangeMarkerEndPositionIsLead = endPositionIsLead; + } - public void setEndPosition(@NotNull VisualPosition endPosition) { - myEndPosition = endPosition; - } - - public boolean isEndPositionIsLead() { - return myEndPositionIsLead; - } - - public void setEndPositionIsLead(boolean endPositionIsLead) { - myEndPositionIsLead = endPositionIsLead; - } - - int startBefore; - int endBefore; - - @Override - protected void changedUpdateImpl(DocumentEvent e) { - if (myIsReleased) return; - startBefore = getStartOffset(); - endBefore = getEndOffset(); - super.changedUpdateImpl(e); - } - - private void invalidateVisualPositions() { - SoftWrapModelImpl model = myEditor.getSoftWrapModel(); - if (!myEditor.offsetToVisualPosition(getStartOffset()).equals(myStartPosition) && model.getSoftWrap(getStartOffset()) == null - || !myEditor.offsetToVisualPosition(getEndOffset()).equals(myEndPosition) && model.getSoftWrap(getEndOffset()) == null) { - myStartPosition = null; - myEndPosition = null; - } + private void invalidateRangeMarkerVisualPositions(RangeMarker marker) { + SoftWrapModelImpl model = myEditor.getSoftWrapModel(); + if (!myEditor.offsetToVisualPosition(marker.getStartOffset()).equals(myRangeMarkerStartPosition) && model.getSoftWrap(marker.getStartOffset()) == null + || !myEditor.offsetToVisualPosition(marker.getEndOffset()).equals(myRangeMarkerEndPosition) && model.getSoftWrap(marker.getEndOffset()) == null) { + myRangeMarkerStartPosition = null; + myRangeMarkerEndPosition = null; } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java index 46db15c333dc..66ddf67e3f31 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -31,7 +31,7 @@ import com.intellij.openapi.editor.ex.DocumentEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion { +class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion { private boolean myIsExpanded; private final Editor myEditor; private final String myPlaceholderText; @@ -94,7 +94,7 @@ public class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion { return super.isValid() && intervalStart() < intervalEnd(); } - public void setExpandedInternal(boolean toExpand) { + void setExpandedInternal(boolean toExpand) { myIsExpanded = toExpand; } @@ -120,6 +120,7 @@ public class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion { return myShouldNeverExpand; } + @Override public String toString() { return "FoldRegion " + (myIsExpanded ? "-" : "+") + "(" + getStartOffset() + ":" + getEndOffset() + ")" + (isValid() ? "" : "(invalid)") + ", placeholder='" + myPlaceholderText + "'";