This commit is contained in:
Alexey Kudravtsev
2017-06-22 15:06:18 +03:00
parent 1ebf229503
commit 50c66cda17
6 changed files with 125 additions and 137 deletions
@@ -29,6 +29,7 @@ import com.intellij.openapi.editor.impl.softwrap.*;
import com.intellij.openapi.editor.impl.softwrap.mapping.CachingSoftWrapDataMapper;
import com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapApplianceManager;
import com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapAwareDocumentParsingListenerAdapter;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.TextRange;
import com.intellij.util.DocumentUtil;
import org.jetbrains.annotations.NotNull;
@@ -46,7 +47,7 @@ import java.util.List;
/**
* Default {@link SoftWrapModelEx} implementation.
* <p/>
* Works as a mix of <code>GoF Facade and Bridge</code>, i.e. delegates the processing to the target sub-components and provides
* Works as a mix of {@code GoF Facade and Bridge}, i.e. delegates the processing to the target sub-components and provides
* utility methods built on top of sub-components API.
* <p/>
* Not thread-safe.
@@ -71,7 +72,7 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
* <p/>
* So, our strategy is to collect information about changed fold regions and process it only when batch folding processing ends.
*/
private final List<TextRange> myDeferredFoldRegions = new ArrayList<>();
private final List<Segment> myDeferredFoldRegions = new ArrayList<>();
private final CachingSoftWrapDataMapper myDataMapper;
private final SoftWrapsStorage myStorage;
@@ -101,18 +102,18 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
/**
* There is a possible case that target document is changed while its editor is inactive (e.g. user opens two editors for classes
* <code>'Part'</code> and <code>'Whole'</code>; activates editor for the class <code>'Whole'</code> and performs 'rename class'
* for <code>'Part'</code> from it). Soft wraps cache is not recalculated during that because corresponding editor is not shown
* {@code 'Part'} and {@code 'Whole'}; activates editor for the class {@code 'Whole'} and performs 'rename class'
* for {@code 'Part'} from it). Soft wraps cache is not recalculated during that because corresponding editor is not shown
* and we lack information about visible area width. Hence, we will need to recalculate the whole soft wraps cache as soon
* as target editor becomes visible.
* <p/>
* Current field serves as a flag for that <code>'dirty document, need complete soft wraps cache recalculation'</code> state.
* Current field serves as a flag for that {@code 'dirty document, need complete soft wraps cache recalculation'} state.
*/
private boolean myDirty;
private boolean myForceAdditionalColumns;
public SoftWrapModelImpl(@NotNull EditorImpl editor) {
SoftWrapModelImpl(@NotNull EditorImpl editor) {
myEditor = editor;
myStorage = new SoftWrapsStorage();
myPainter = new CompositeSoftWrapPainter(editor);
@@ -161,7 +162,7 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
myPainter.reinit();
}
if ((myUseSoftWraps ^ softWrapsUsedBefore) || (tabWidthBefore >= 0 && myTabWidth != tabWidthBefore) || fontsChanged) {
if (myUseSoftWraps != softWrapsUsedBefore || tabWidthBefore >= 0 && myTabWidth != tabWidthBefore || fontsChanged) {
myApplianceManager.reset();
myDeferredFoldRegions.clear();
myStorage.removeAll();
@@ -250,7 +251,7 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
/**
* @return total number of soft wrap-introduced new visual lines
*/
public int getSoftWrapsIntroducedLinesNumber() {
int getSoftWrapsIntroducedLinesNumber() {
return myStorage.getSoftWraps().size(); // Assuming that soft wrap has single line feed all the time
}
@@ -308,12 +309,10 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
* Encapsulates preparations for performing document dimension mapping (e.g. visual to logical position) and answers
* if soft wraps-aware processing should be used (e.g. there is no need to consider soft wraps if user configured them
* not to be used).
*
* @return <code>true</code> if soft wraps-aware processing should be used; <code>false</code> otherwise
*/
public boolean prepareToMapping() {
public void prepareToMapping() {
if (myUpdateInProgress || myBulkUpdateInProgress || !isSoftWrappingEnabled()) {
return false;
return;
}
if (myDirty) {
@@ -322,16 +321,16 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
myDeferredFoldRegions.clear();
myDirty = false;
}
return myApplianceManager.recalculateIfNecessary();
myApplianceManager.recalculateIfNecessary();
}
/**
* Allows to answer if given visual position points to soft wrap-introduced virtual space.
*
* @param visual target visual position to check
* @return <code>true</code> if given visual position points to soft wrap-introduced virtual space;
* <code>false</code> otherwise
* @return {@code true} if given visual position points to soft wrap-introduced virtual space;
* {@code false} otherwise
*/
@Override
public boolean isInsideSoftWrap(@NotNull VisualPosition visual) {
@@ -342,8 +341,8 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
* Allows to answer if given visual position points to soft wrap-introduced virtual space or points just before soft wrap.
*
* @param visual target visual position to check
* @return <code>true</code> if given visual position points to soft wrap-introduced virtual space;
* <code>false</code> otherwise
* @return {@code true} if given visual position points to soft wrap-introduced virtual space;
* {@code false} otherwise
*/
@Override
public boolean isInsideOrBeforeSoftWrap(@NotNull VisualPosition visual) {
@@ -470,7 +469,7 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
// We delay processing of changed fold regions till the invocation of onFoldProcessingEnd(), as
// FoldingModel can return inconsistent data before that moment.
myDeferredFoldRegions.add(new TextRange(region.getStartOffset(), region.getEndOffset()));
myDeferredFoldRegions.add(region);
}
@Override
@@ -521,7 +520,7 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
myDeferredFoldRegions.clear();
}
public void recalculate() {
void recalculate() {
myApplianceManager.reset();
myStorage.removeAll();
myDeferredFoldRegions.clear();
@@ -542,6 +541,7 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
return ((SoftWrapModelEx)editor.getSoftWrapModel()).getEditorTextRepresentationHelper();
}
@Override
public EditorTextRepresentationHelper getEditorTextRepresentationHelper() {
return myEditorTextRepresentationHelper;
}
@@ -573,7 +573,7 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter
}
@TestOnly
public void validateState() {
void validateState() {
Document document = myEditor.getDocument();
if (myEditor.getDocument().isInBulkUpdate()) return;
FoldingModel foldingModel = myEditor.getFoldingModel();
@@ -31,13 +31,11 @@ import java.util.Collections;
import java.util.List;
public class CachingSoftWrapDataMapper implements SoftWrapAwareDocumentParsingListener, Dumpable {
private static final Logger LOG = Logger.getInstance(CachingSoftWrapDataMapper.class);
private final List<SoftWrapImpl> myAffectedByUpdateSoftWraps = new ArrayList<>();
private final EditorEx myEditor;
private final SoftWrapsStorage myStorage;
private final List<SoftWrapImpl> myAffectedByUpdateSoftWraps = new ArrayList<>();
private final EditorEx myEditor;
private final SoftWrapsStorage myStorage;
public CachingSoftWrapDataMapper(@NotNull EditorEx editor, @NotNull SoftWrapsStorage storage)
{
@@ -92,8 +90,6 @@ public class CachingSoftWrapDataMapper implements SoftWrapAwareDocumentParsingLi
/**
* Determines which soft wraps were not affected by recalculation, and shifts them to their new offsets.
*
* @return Change in soft wraps count after recalculation
*/
private void advanceSoftWrapOffsets(@NotNull IncrementalCacheUpdateEvent event) {
int lengthDiff = event.getLengthDiff();
@@ -20,13 +20,13 @@ import org.jetbrains.annotations.NotNull;
class EditorPosition implements Cloneable {
public int logicalLine;
public int offset;
public int x;
int logicalLine;
int offset;
int x;
private final Editor myEditor;
EditorPosition(@NotNull Editor editor) {
private EditorPosition(@NotNull Editor editor) {
myEditor = editor;
}
@@ -36,7 +36,7 @@ class EditorPosition implements Cloneable {
this.offset = offset;
}
public void onNewLine() {
void onNewLine() {
logicalLine++;
x = 0;
offset++;
@@ -43,7 +43,7 @@ public class IncrementalCacheUpdateEvent {
private int myNewEndLogicalLine = -1;
/**
* Creates new <code>IncrementalCacheUpdateEvent</code> object on the basis on the given event object that describes
* Creates new {@code IncrementalCacheUpdateEvent} object on the basis on the given event object that describes
* document change that caused cache update.
* <p/>
* This constructor is assumed to be used <b>before</b> the document change, {@link #updateAfterDocumentChange(Document)}
@@ -56,7 +56,7 @@ public class IncrementalCacheUpdateEvent {
}
/**
* Creates new <code>IncrementalCacheUpdateEvent</code> object for the event not changing document length
* Creates new {@code IncrementalCacheUpdateEvent} object for the event not changing document length
* (like expansion of folded region).
*/
IncrementalCacheUpdateEvent(int startOffset, int endOffset, @NotNull EditorImpl editor) {
@@ -65,7 +65,7 @@ public class IncrementalCacheUpdateEvent {
}
/**
* Creates new <code>IncrementalCacheUpdateEvent</code> object that is configured to perform whole reparse of the given
* Creates new {@code IncrementalCacheUpdateEvent} object that is configured to perform whole reparse of the given
* document.
*
* @param document target document to reparse
@@ -101,7 +101,7 @@ public class IncrementalCacheUpdateEvent {
SoftWrapModelImpl softWrapModel = editor.getSoftWrapModel();
int wrapIndex = softWrapModel.getSoftWrapIndex(offset);
int prevSoftWrapIndex = wrapIndex < 0 ? (- wrapIndex - 2) : wrapIndex - (beforeSoftWrap ? 1 : 0);
int prevSoftWrapIndex = wrapIndex < 0 ? - wrapIndex - 2 : wrapIndex - (beforeSoftWrap ? 1 : 0);
SoftWrap prevSoftWrap = prevSoftWrapIndex < 0 ? null : softWrapModel.getRegisteredSoftWraps().get(prevSoftWrapIndex);
int visualLineStartOffset = prevSoftWrap == null ? startOffset : Math.max(startOffset, prevSoftWrap.getStart());
@@ -118,7 +118,7 @@ public class IncrementalCacheUpdateEvent {
}
}
public void updateAfterDocumentChange(@NotNull Document document) {
void updateAfterDocumentChange(@NotNull Document document) {
myNewEndLogicalLine = document.getLineNumber(myMandatoryEndOffset);
}
@@ -133,14 +133,14 @@ public class IncrementalCacheUpdateEvent {
* Returns logical position, from which soft wrap recalculation should start
*/
@NotNull
public LogicalPosition getStartLogicalPosition() {
LogicalPosition getStartLogicalPosition() {
return myStartLogicalPosition;
}
/**
* Returns offset, till which soft wrap recalculation should proceed
*/
public int getMandatoryEndOffset() {
int getMandatoryEndOffset() {
return myMandatoryEndOffset;
}
@@ -159,7 +159,7 @@ public class IncrementalCacheUpdateEvent {
/**
* Returns change in document length for the event causing soft wrap recalculation.
*/
public int getLengthDiff() {
int getLengthDiff() {
return myLengthDiff;
}
@@ -81,25 +81,25 @@ public class SoftWrapApplianceManager implements Dumpable {
CUSTOM
}
private final List<SoftWrapAwareDocumentParsingListener> myListeners = new ArrayList<>();
private final ProcessingContext myContext = new ProcessingContext();
private final FontTypesStorage myOffset2fontType = new FontTypesStorage();
private final WidthsStorage myOffset2widthInPixels = new WidthsStorage();
private final List<SoftWrapAwareDocumentParsingListener> myListeners = new ArrayList<>();
private final ProcessingContext myContext = new ProcessingContext();
private final FontTypesStorage myOffset2fontType = new FontTypesStorage();
private final WidthsStorage myOffset2widthInPixels = new WidthsStorage();
private final SoftWrapsStorage myStorage;
private final EditorImpl myEditor;
private SoftWrapPainter myPainter;
private final CachingSoftWrapDataMapper myDataMapper;
private final SoftWrapsStorage myStorage;
private final EditorImpl myEditor;
private SoftWrapPainter myPainter;
private final CachingSoftWrapDataMapper myDataMapper;
/**
* Visual area width change causes soft wraps addition/removal, so, we want to update <code>'y'</code> coordinate
* Visual area width change causes soft wraps addition/removal, so, we want to update {@code 'y'} coordinate
* of the editor viewport then. For example, we observe particular text region at the 'vcs diff' control and change
* its width. We would like to see the same text range at the viewport then.
* <p/>
* This field holds offset of the text range that is shown at the top-left viewport position. It's used as an anchor
* during viewport's <code>'y'</code> coordinate adjustment on visual area width change.
* during viewport's {@code 'y'} coordinate adjustment on visual area width change.
*/
private int myLastTopLeftCornerOffset = 0;
private int myLastTopLeftCornerOffset;
private VisibleAreaWidthProvider myWidthProvider;
private LineWrapPositionStrategy myLineWrapPositionStrategy;
@@ -110,7 +110,7 @@ public class SoftWrapApplianceManager implements Dumpable {
private boolean myInProgress;
private boolean myIsDirty = true;
private IncrementalCacheUpdateEvent myDocumentChangedEvent;
private int myAvailableWidth = QUICK_DUMMY_WRAPPING;
private int myAvailableWidth = QUICK_DUMMY_WRAPPING;
public SoftWrapApplianceManager(@NotNull SoftWrapsStorage storage,
@@ -144,7 +144,7 @@ public class SoftWrapApplianceManager implements Dumpable {
myLineWrapPositionStrategy = null;
}
public void recalculate(IncrementalCacheUpdateEvent e) {
private void recalculate(IncrementalCacheUpdateEvent e) {
if (myIsDirty) {
return;
}
@@ -158,7 +158,7 @@ public class SoftWrapApplianceManager implements Dumpable {
onRecalculationEnd();
}
public void recalculate(List<? extends Segment> ranges) {
public void recalculate(@NotNull List<? extends Segment> ranges) {
if (myIsDirty) {
return;
}
@@ -171,7 +171,7 @@ public class SoftWrapApplianceManager implements Dumpable {
int startDiff = o1.getStartOffset() - o2.getStartOffset();
return startDiff == 0 ? o2.getEndOffset() - o1.getEndOffset() : startDiff;
});
final int[] lastRecalculatedOffset = new int[] {0};
final int[] lastRecalculatedOffset = {0};
SoftWrapAwareDocumentParsingListenerAdapter listener = new SoftWrapAwareDocumentParsingListenerAdapter() {
@Override
public void onRecalculationEnd(@NotNull IncrementalCacheUpdateEvent event) {
@@ -196,8 +196,8 @@ public class SoftWrapApplianceManager implements Dumpable {
}
/**
* @return <code>true</code> if soft wraps were really re-calculated;
* <code>false</code> if it's not possible to do at the moment (e.g. current editor is not shown and we don't
* @return {@code true} if soft wraps were really re-calculated;
* {@code false} if it's not possible to do at the moment (e.g. current editor is not shown and we don't
* have information about viewport width)
*/
private boolean recalculateSoftWraps() {
@@ -266,7 +266,7 @@ public class SoftWrapApplianceManager implements Dumpable {
}
}
}
private void doRecalculateSoftWraps(IncrementalCacheUpdateEvent event, int endOffsetUpperEstimate) {
// Preparation.
myContext.reset();
@@ -390,7 +390,7 @@ public class SoftWrapApplianceManager implements Dumpable {
* Encapsulates logic of processing given collapsed fold region.
*
* @param foldRegion target collapsed fold region to process
* @return <code>true</code> if no further calculation is required
* @return {@code true} if no further calculation is required
*/
private boolean processCollapsedFoldRegion(FoldRegion foldRegion) {
Document document = myEditor.getDocument();
@@ -472,9 +472,9 @@ public class SoftWrapApplianceManager implements Dumpable {
* (target token start offset is identified by {@link ProcessingContext#tokenStartOffset}; end offset is stored
* at {@link ProcessingContext#tokenEndOffset}).
* <p/>
* <code>'Token'</code> here stands for the number of subsequent symbols that are represented using the same font by IJ editor.
* {@code 'Token'} here stands for the number of subsequent symbols that are represented using the same font by IJ editor.
*
* @return <code>true</code> if no further calculation is required
* @return {@code true} if no further calculation is required
*/
private boolean processNonFoldToken() {
int limit = 3 * (myContext.tokenEndOffset - myContext.lineStartPosition.offset);
@@ -559,7 +559,7 @@ public class SoftWrapApplianceManager implements Dumpable {
*/
private int[] offsetToX(int offset, int c) {
if (myOffset2widthInPixels.end > offset
&& (myOffset2widthInPixels.anchor + myOffset2widthInPixels.end > offset))
&& myOffset2widthInPixels.anchor + myOffset2widthInPixels.end > offset)
{
int width = myOffset2widthInPixels.data[offset - myOffset2widthInPixels.anchor];
return new int[] {myContext.currentPosition.x + width + myContext.getInlaysWidth(), width};
@@ -623,7 +623,7 @@ public class SoftWrapApplianceManager implements Dumpable {
myContext.onNonLineFeedSymbol(Character.codePointAt(myContext.text, offset));
return false;
}
else if (actualSoftWrapOffset < offset) {
if (actualSoftWrapOffset < offset) {
if (revertedToFoldRegion == null) {
while (myContext.currentPosition.offset > actualSoftWrapOffset) {
int prevOffset = Character.offsetByCodePoints(myContext.text, myContext.currentPosition.offset, -1);
@@ -685,14 +685,14 @@ public class SoftWrapApplianceManager implements Dumpable {
* <p/>
* There is a possible case that no soft wrap is created and registered. That is true, for example, for a situation when
* we have a long line of text that doesn't contain white spaces, operators or any other symbols that may be used
* as a <code>'wrap points'</code>. We just left such lines as-is.
* as a {@code 'wrap points'}. We just left such lines as-is.
*
* @param minOffset min line <code>'wrap point'</code> offset
* @param preferredOffset preferred <code>'wrap point'</code> offset, i.e. max offset which symbol doesn't exceed right margin
* @param maxOffset max line <code>'wrap point'</code> offset
* @param minOffset min line {@code 'wrap point'} offset
* @param preferredOffset preferred {@code 'wrap point'} offset, i.e. max offset which symbol doesn't exceed right margin
* @param maxOffset max line {@code 'wrap point'} offset
* @param spaceSize current space width in pixels
* @param lineData object that encapsulates information about currently processed logical line
* @return newly created and registered soft wrap if any; <code>null</code> otherwise
* @return newly created and registered soft wrap if any; {@code null} otherwise
*/
@Nullable
private SoftWrapImpl registerSoftWrap(int minOffset, int preferredOffset, int maxOffset, int spaceSize, LogicalLineData lineData) {
@@ -715,9 +715,9 @@ public class SoftWrapApplianceManager implements Dumpable {
}
if (softWrapOffset >= lineData.endLineOffset || softWrapOffset < 0 || softWrapOffset <= minOffset
|| (myCustomIndentUsedLastTime && softWrapOffset == lineData.nonWhiteSpaceSymbolOffset)
|| (softWrapOffset > preferredOffset && myContext.lastFoldStartPosition != null // Prefer to wrap on fold region backwards
&& myContext.lastFoldStartPosition.offset <= preferredOffset)) // to wrapping forwards.
|| myCustomIndentUsedLastTime && softWrapOffset == lineData.nonWhiteSpaceSymbolOffset
|| softWrapOffset > preferredOffset && myContext.lastFoldStartPosition != null // Prefer to wrap on fold region backwards
&& myContext.lastFoldStartPosition.offset <= preferredOffset) // to wrapping forwards.
{
return null;
}
@@ -732,7 +732,7 @@ public class SoftWrapApplianceManager implements Dumpable {
int indentInPixels = myPainter.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
if (myCustomIndentUsedLastTime) {
indentInColumns = myCustomIndentValueUsedLastTime + lineData.indentInColumns;
indentInPixels += lineData.indentInPixels + (myCustomIndentValueUsedLastTime * spaceSize);
indentInPixels += lineData.indentInPixels + myCustomIndentValueUsedLastTime * spaceSize;
}
SoftWrapImpl result = new SoftWrapImpl(
new TextChangeImpl("\n" + StringUtil.repeatSymbol(' ', indentInColumns), offset, offset),
@@ -753,8 +753,8 @@ public class SoftWrapApplianceManager implements Dumpable {
*
* @param minOffset min offset to use (inclusive)
* @param preferredOffset max offset to use (inclusive)
* @return offset of the space symbol that belongs to <code>[minOffset; preferredOffset]</code> interval if any;
* <code>'-1'</code> otherwise
* @return offset of the space symbol that belongs to {@code [minOffset; preferredOffset]} interval if any;
* {@code '-1'} otherwise
*/
private int calculateBackwardSpaceOffsetIfPossible(int minOffset, int preferredOffset) {
// There is a possible case that we have a long line that contains many non-white space symbols eligible for performing
@@ -780,10 +780,10 @@ public class SoftWrapApplianceManager implements Dumpable {
*
* @param minOffset min offset to use (inclusive)
* @param preferredOffset max offset to use (inclusive)
* @return soft wrap offset that belongs to <code>[minOffset; preferredOffset]</code> interval if any;
* <code>'-1'</code> otherwise
* @return soft wrap offset that belongs to {@code [minOffset; preferredOffset]} interval if any;
* {@code '-1'} otherwise
*/
public int calculateBackwardOffsetForEasternLanguageIfPossible(int minOffset, int preferredOffset) {
private int calculateBackwardOffsetForEasternLanguageIfPossible(int minOffset, int preferredOffset) {
// There is a possible case that we have a long line that contains many non-white space symbols eligible for performing
// soft wrap that are preceded by white space symbol. We don't want to create soft wrap that is located so far from the
// preferred position then, hence, we check white space symbol existence not more than specific number of symbols back.
@@ -818,8 +818,8 @@ public class SoftWrapApplianceManager implements Dumpable {
* soft wrap indent is changed etc). This method encapsulates that logic, i.e. it checks if necessary conditions are satisfied
* and updates internal state as necessary.
*
* @return <code>true</code> if re-calculation logic was performed;
* <code>false</code> otherwise (e.g. we need to perform re-calculation but current editor is now shown, i.e. we don't
* @return {@code true} if re-calculation logic was performed;
* {@code false} otherwise (e.g. we need to perform re-calculation but current editor is now shown, i.e. we don't
* have information about viewport width
*/
public boolean recalculateIfNecessary() {
@@ -832,7 +832,7 @@ public class SoftWrapApplianceManager implements Dumpable {
IndentType currentIndentType = getIndentToUse();
boolean useCustomIndent = currentIndentType == IndentType.CUSTOM;
int currentCustomIndent = myEditor.getSettings().getCustomSoftWrapIndent();
if (useCustomIndent ^ myCustomIndentUsedLastTime || (useCustomIndent && myCustomIndentValueUsedLastTime != currentCustomIndent)) {
if (useCustomIndent ^ myCustomIndentUsedLastTime || useCustomIndent && myCustomIndentValueUsedLastTime != currentCustomIndent) {
indentChanged = true;
}
myCustomIndentUsedLastTime = useCustomIndent;
@@ -922,7 +922,7 @@ public class SoftWrapApplianceManager implements Dumpable {
* Registers given listener within the current manager.
*
* @param listener listener to register
* @return <code>true</code> if this collection changed as a result of the call; <code>false</code> otherwise
* @return {@code true} if this collection changed as a result of the call; {@code false} otherwise
*/
public boolean addListener(@NotNull SoftWrapAwareDocumentParsingListener listener) {
return myListeners.add(listener);
@@ -933,17 +933,17 @@ public class SoftWrapApplianceManager implements Dumpable {
}
@SuppressWarnings({"ForLoopReplaceableByForEach"})
private void notifyListenersOnCacheUpdateStart(IncrementalCacheUpdateEvent event) {
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < myListeners.size(); i++) {
// Avoid unnecessary Iterator object construction as this method is expected to be called frequently.
SoftWrapAwareDocumentParsingListener listener = myListeners.get(i);
listener.onCacheUpdateStart(event);
}
}
@SuppressWarnings({"ForLoopReplaceableByForEach"})
private void notifyListenersOnCacheUpdateEnd(IncrementalCacheUpdateEvent event) {
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < myListeners.size(); i++) {
// Avoid unnecessary Iterator object construction as this method is expected to be called frequently.
SoftWrapAwareDocumentParsingListener listener = myListeners.get(i);
@@ -1000,10 +1000,10 @@ public class SoftWrapApplianceManager implements Dumpable {
*/
private class LogicalLineData {
public int indentInColumns;
public int indentInPixels;
public int endLineOffset;
public int nonWhiteSpaceSymbolOffset;
int indentInColumns;
int indentInPixels;
int endLineOffset;
int nonWhiteSpaceSymbolOffset;
public void update(int logicalLine, int spaceWidth, int plainSpaceWidth) {
Document document = myEditor.getDocument();
@@ -1061,6 +1061,7 @@ public class SoftWrapApplianceManager implements Dumpable {
* This interface is introduced mostly for encapsulating GUI-specific values retrieval and make it possible to write
* tests for soft wraps processing.
*/
@FunctionalInterface
public interface VisibleAreaWidthProvider {
int getVisibleAreaWidth();
}
@@ -1112,9 +1113,9 @@ public class SoftWrapApplianceManager implements Dumpable {
* token1 token2-toke|n3
* | &lt;- right margin
* </pre>
* It's possible that <code>'token1'</code>, white spaces and <code>'token2'</code> use different font types and
* soft wrapping should be performed between <code>'token1'</code> and <code>'token2'</code>. We need to be able to
* match offsets of <code>'token2'</code> to font types then.
* It's possible that {@code 'token1'}, white spaces and {@code 'token2'} use different font types and
* soft wrapping should be performed between {@code 'token1'} and {@code 'token2'}. We need to be able to
* match offsets of {@code 'token2'} to font types then.
* <p/>
* There is an additional trick here - there is a possible case that a bunch number of adjacent symbols use the same font
* type (are marked by {@link IterationState} as a single token. That is often the case for plain text). We don't want to
@@ -1126,13 +1127,12 @@ public class SoftWrapApplianceManager implements Dumpable {
* This is primitive array-based data structure that contains {@code offset -> font type} mappings.
*/
private static class FontTypesStorage {
private int[] myStarts = new int[256];
private int[] myEnds = new int[256];
private int[] myData = new int[256];
@JdkConstants.FontStyle private int[] myData = new int[256];
private int myLastIndex = -1;
public void fill(int start, int end, int value) {
void fill(int start, int end, @JdkConstants.FontStyle int value) {
if (myLastIndex >= 0 && myData[myLastIndex] == value && myEnds[myLastIndex] == start) {
myEnds[myLastIndex] = end;
return;
@@ -1149,8 +1149,9 @@ public class SoftWrapApplianceManager implements Dumpable {
* Tries to retrieve stored value for the given offset if any;
*
* @param offset target offset
* @return target value if any is stored; <code>-1</code> otherwise
* @return target value if any is stored; {@code -1} otherwise
*/
@JdkConstants.FontStyle
public int get(int offset) {
// The key is array index plus anchor; the value is array value.
if (myLastIndex < 0) {
@@ -1184,37 +1185,36 @@ public class SoftWrapApplianceManager implements Dumpable {
}
private class ProcessingContext {
final PrimitiveIntMap fontType2spaceWidth = new PrimitiveIntMap();
final LogicalLineData logicalLineData = new LogicalLineData();
public final PrimitiveIntMap fontType2spaceWidth = new PrimitiveIntMap();
public final LogicalLineData logicalLineData = new LogicalLineData();
public CharSequence text;
public EditorPosition lineStartPosition;
public EditorPosition currentPosition;
CharSequence text;
EditorPosition lineStartPosition;
EditorPosition currentPosition;
/**
* Start position of the last collapsed fold region that is located at the current visual line and can be used as a fall back
* position for soft wrapping.
*/
public EditorPosition lastFoldStartPosition;
public EditorPosition lastFoldEndPosition;
EditorPosition lastFoldStartPosition;
EditorPosition lastFoldEndPosition;
/** A fold region referenced by the {@link #lastFoldStartPosition}. */
public FoldRegion lastFold;
public SoftWrapImpl delayedSoftWrap;
public int reservedWidthInPixels;
FoldRegion lastFold;
SoftWrapImpl delayedSoftWrap;
int reservedWidthInPixels;
/**
* Min offset to use when new soft wrap should be introduced. I.e. every time we detect that text exceeds visual width,
*/
public int softWrapStartOffset;
public int rangeEndOffset;
public int tokenStartOffset;
public int tokenEndOffset;
public boolean nextIsFoldRegion;
int softWrapStartOffset;
int rangeEndOffset;
int tokenStartOffset;
int tokenEndOffset;
boolean nextIsFoldRegion;
@JdkConstants.FontStyle
public int fontType;
public boolean skipToLineEnd;
int fontType;
boolean skipToLineEnd;
public List<Inlay> inlays;
public int inlayIndex;
List<Inlay> inlays;
int inlayIndex;
@Override
public String toString() {
@@ -1244,11 +1244,11 @@ public class SoftWrapApplianceManager implements Dumpable {
inlayIndex = 0;
}
public int getSpaceWidth() {
int getSpaceWidth() {
return getSpaceWidth(fontType);
}
public int getPlainSpaceWidth() {
int getPlainSpaceWidth() {
return getSpaceWidth(Font.PLAIN);
}
@@ -1265,8 +1265,7 @@ public class SoftWrapApplianceManager implements Dumpable {
/**
* Asks current context to update its state assuming that it begins to point to the line next to its current position.
*/
@SuppressWarnings("MagicConstant")
public void onNewLine() {
void onNewLine() {
currentPosition.onNewLine();
softWrapStartOffset = currentPosition.offset;
clearLastFoldInfo();
@@ -1285,10 +1284,10 @@ public class SoftWrapApplianceManager implements Dumpable {
lastFold = null;
}
public void onNonLineFeedSymbol(int c) {
void onNonLineFeedSymbol(int c) {
int[] metrics;
if (myOffset2widthInPixels.end > myContext.currentPosition.offset
&& (myOffset2widthInPixels.anchor + myOffset2widthInPixels.end > myContext.currentPosition.offset))
&& myOffset2widthInPixels.anchor + myOffset2widthInPixels.end > myContext.currentPosition.offset)
{
int width = myOffset2widthInPixels.data[myContext.currentPosition.offset - myOffset2widthInPixels.anchor];
@@ -1300,8 +1299,7 @@ public class SoftWrapApplianceManager implements Dumpable {
onNonLineFeedSymbol(c, metrics);
}
@SuppressWarnings("MagicConstant")
public void onNonLineFeedSymbol(int codePoint, int[] metrics) { // {newX, actualWidth}
void onNonLineFeedSymbol(int codePoint, int[] metrics) { // {newX, actualWidth}
if (myOffset2widthInPixels.anchor <= 0) {
myOffset2widthInPixels.anchor = currentPosition.offset;
}
@@ -1368,9 +1366,9 @@ public class SoftWrapApplianceManager implements Dumpable {
/**
* Asks current context to update its state in order to show to the first symbol of the next visual line if it belongs to
* [{@link #tokenStartOffset}; {@link #skipToLineEnd} is set to <code>'true'</code> otherwise
* [{@link #tokenStartOffset}; {@link #skipToLineEnd} is set to {@code 'true'} otherwise
*/
public boolean tryToShiftToNextLine() {
boolean tryToShiftToNextLine() {
while (currentPosition.offset < tokenEndOffset) {
int c = Character.codePointAt(text, currentPosition.offset);
if (c == '\n') {
@@ -1386,12 +1384,10 @@ public class SoftWrapApplianceManager implements Dumpable {
}
/**
* Allows to answer if point with the given <code>'x'</code> coordinate exceeds visual area's right edge.
*
* @param x target <code>'x'</code> coordinate to check
* @return <code>true</code> if given <code>'x'</code> coordinate exceeds visual area's right edge; <code>false</code> otherwise
* @param x target {@code 'x'} coordinate to check
* @return {@code true} if given {@code 'x'} coordinate exceeds visual area's right edge; {@code false} otherwise
*/
public boolean exceedsVisualEdge(int x) {
boolean exceedsVisualEdge(int x) {
return x > myVisibleAreaWidth;
}
}
@@ -19,7 +19,6 @@
*/
package com.intellij.openapi.vfs.newvfs.impl;
import com.google.common.annotations.VisibleForTesting;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationUtil;
import com.intellij.openapi.application.impl.ApplicationImpl;
@@ -53,8 +52,7 @@ import java.util.Collection;
import java.util.Collections;
public class VirtualFileImpl extends VirtualFileSystemEntry {
@VisibleForTesting
public VirtualFileImpl(int id, VfsData.Segment segment, VirtualDirectoryImpl parent) {
VirtualFileImpl(int id, VfsData.Segment segment, VirtualDirectoryImpl parent) {
super(id, segment, parent);
}
@@ -147,9 +145,7 @@ public class VirtualFileImpl extends VirtualFileSystemEntry {
try {
// execute in impatient mode to not deadlock when the indexing process waits in under write action for queue to load contents in other threads
// and that other thread asks JspManager for encoding which requires read action for PSI
((ApplicationImpl)ApplicationManager.getApplication()).executeByImpatientReader(() -> {
LoadTextUtil.detectCharsetAndSetBOM(this, bytes, fileType);
});
((ApplicationImpl)ApplicationManager.getApplication()).executeByImpatientReader(() -> LoadTextUtil.detectCharsetAndSetBOM(this, bytes, fileType));
}
catch (ApplicationUtil.CannotRunReadActionException ignored) {
}