diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index 3d51b6ba470c..2a2249b60e57 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -59,7 +59,8 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { private final List myGuardedBlocks = new ArrayList(); private ReadonlyFragmentModificationHandler myReadonlyFragmentModificationHandler; - private final LineSet myLineSet = new LineSet(); + private final Object myLineSetLock = new String("line set lock"); + private volatile LineSet myLineSet; private volatile ImmutableText myText; private volatile SoftReference myTextString; @@ -112,7 +113,6 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { public DocumentImpl(@NotNull CharSequence chars, boolean forUseInNonAWTThread) { assertValidSeparators(chars); myText = ImmutableText.valueOf(chars); - myLineSet.documentCreated(this); setCyclicBufferSize(0); setModificationStamp(LocalTimeCounter.currentTime()); myAssertThreading = !forUseInNonAWTThread; @@ -127,6 +127,22 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { } } + private LineSet getLineSet() { + LineSet lineSet = myLineSet; + if (lineSet == null) { + synchronized (myLineSetLock) { + lineSet = myLineSet; + if (lineSet == null) { + lineSet = new LineSet(); + lineSet.documentCreated(this); + myLineSet = lineSet; + } + } + } + + return lineSet; + } + @Override @NotNull public char[] getChars() { @@ -159,11 +175,12 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { CharSequence text = myText; RangeMarker caretMarker = caretOffset < 0 || caretOffset > getTextLength() ? null : createRangeMarker(caretOffset, caretOffset); try { - for (int line = 0; line < myLineSet.getLineCount(); line++) { - if (inChangedLinesOnly && !myLineSet.isModified(line)) continue; + LineSet lineSet = getLineSet(); + for (int line = 0; line < lineSet.getLineCount(); line++) { + if (inChangedLinesOnly && !lineSet.isModified(line)) continue; int whiteSpaceStart = -1; - final int lineEnd = myLineSet.getLineEnd(line) - myLineSet.getSeparatorLength(line); - int lineStart = myLineSet.getLineStart(line); + final int lineEnd = lineSet.getLineEnd(line) - lineSet.getSeparatorLength(line); + int lineStart = lineSet.getLineStart(line); for (int offset = lineEnd - 1; offset >= lineStart; offset--) { char c = text.charAt(offset); if (c != ' ' && c != '\t') { @@ -228,12 +245,13 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { markers.add(marker); } } + LineSet lineSet = getLineSet(); lineLoop: - for (int line = 0; line < myLineSet.getLineCount(); line++) { - if (inChangedLinesOnly && !myLineSet.isModified(line)) continue; + for (int line = 0; line < lineSet.getLineCount(); line++) { + if (inChangedLinesOnly && !lineSet.isModified(line)) continue; int whiteSpaceStart = -1; - final int lineEnd = myLineSet.getLineEnd(line) - myLineSet.getSeparatorLength(line); - int lineStart = myLineSet.getLineStart(line); + final int lineEnd = lineSet.getLineEnd(line) - lineSet.getSeparatorLength(line); + int lineStart = lineSet.getLineStart(line); for (int offset = lineEnd - 1; offset >= lineStart; offset--) { char c = text.charAt(offset); if (c != ' ' && c != '\t') { @@ -644,19 +662,20 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { @Override public void clearLineModificationFlags() { - myLineSet.clearModificationFlags(); + getLineSet().clearModificationFlags(); } public void clearLineModificationFlagsExcept(@NotNull List caretLines) { List modifiedLines = new ArrayList(caretLines.size()); + LineSet lineSet = getLineSet(); for (Integer line : caretLines) { - if (line != null && line >= 0 && line < myLineSet.getLineCount() && myLineSet.isModified(line)) { + if (line != null && line >= 0 && line < lineSet.getLineCount() && lineSet.isModified(line)) { modifiedLines.add(line); } } clearLineModificationFlags(); for (Integer line : modifiedLines) { - myLineSet.setModified(line); + lineSet.setModified(line); } } @@ -725,7 +744,12 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { try { if (LOG.isDebugEnabled()) LOG.debug(event.toString()); - myLineSet.changedUpdate(event); + synchronized (myLineSetLock) { + LineSet lineSet = myLineSet; + if (lineSet != null) { + lineSet.changedUpdate(event); + } + } setModificationStamp(newModificationStamp); if (!ShutDownTracker.isShutdownHookRunning()) { @@ -847,39 +871,39 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { @Override public int getLineNumber(final int offset) { - return myLineSet.findLineIndex(offset); + return getLineSet().findLineIndex(offset); } @Override @NotNull public LineIterator createLineIterator() { - return myLineSet.createIterator(); + return getLineSet().createIterator(); } @Override public final int getLineStartOffset(final int line) { if (line == 0) return 0; // otherwise it crashed for zero-length document - return myLineSet.getLineStart(line); + return getLineSet().getLineStart(line); } @Override public final int getLineEndOffset(int line) { if (getTextLength() == 0 && line == 0) return 0; - int result = myLineSet.getLineEnd(line) - getLineSeparatorLength(line); + int result = getLineSet().getLineEnd(line) - getLineSeparatorLength(line); assert result >= 0; return result; } @Override public final int getLineSeparatorLength(int line) { - int separatorLength = myLineSet.getSeparatorLength(line); + int separatorLength = getLineSet().getSeparatorLength(line); assert separatorLength >= 0; return separatorLength; } @Override public final int getLineCount() { - int lineCount = myLineSet.getLineCount(); + int lineCount = getLineSet().getLineCount(); assert lineCount >= 0; return lineCount; }