From 846e6be9f93290c18ac7ca10150aa0e196edc4c8 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Jul 2014 14:21:43 +0400 Subject: [PATCH] range markers optimisations: create fewer markers in OpenFileDescriptor and LazyMarkerFactory --- .../openapi/editor/impl/DocumentImpl.java | 4 +- .../editor/LazyRangeMarkerFactory.java | 265 +------------- .../execution/DelayedDocumentWatcher.java | 4 +- .../impl/LazyRangeMarkerFactoryImpl.java | 323 ++++++++++++++++++ .../impl/TrailingSpacesStripper.java | 12 +- .../impl/FileDocumentManagerImpl.java | 1 + .../src/META-INF/PlatformExtensions.xml | 3 +- .../openapi/editor/impl/RangeMarkerTest.java | 44 ++- .../{ => impl}/StripTrailingSpacesTest.java | 4 +- .../LightPlatformCodeInsightTestCase.java | 2 +- 10 files changed, 384 insertions(+), 278 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java rename platform/platform-impl/src/com/intellij/openapi/{fileEditor => editor}/impl/TrailingSpacesStripper.java (97%) rename platform/platform-tests/testSrc/com/intellij/openapi/editor/{ => impl}/StripTrailingSpacesTest.java (98%) 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 fa234e109d49..0c0e19667c63 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 @@ -174,7 +174,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { * @deprecated should be replaced with {@link #stripTrailingSpaces(com.intellij.openapi.project.Project, boolean, boolean, java.util.List)} * once multicaret logic will become unconditional (not controlled by configuration flag) */ - public boolean stripTrailingSpaces(@Nullable final Project project, + boolean stripTrailingSpaces(@Nullable final Project project, boolean inChangedLinesOnly, boolean virtualSpaceEnabled, int caretLine, @@ -230,7 +230,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { /** * @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret(s) being in the way */ - public boolean stripTrailingSpaces(@Nullable final Project project, + boolean stripTrailingSpaces(@Nullable final Project project, boolean inChangedLinesOnly, boolean virtualSpaceEnabled, @NotNull List caretOffsets) { diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java index 3780e3a79e0c..942a33aaace8 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java @@ -15,276 +15,19 @@ */ package com.intellij.openapi.editor; -import com.intellij.codeStyle.CodeStyleFacade; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.editor.event.DocumentAdapter; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.SmartList; -import com.intellij.util.containers.WeakList; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class LazyRangeMarkerFactory { - private final Project myProject; - private static final Key> LAZY_MARKERS_KEY = Key.create("LAZY_MARKERS_KEY"); +public abstract class LazyRangeMarkerFactory { public static LazyRangeMarkerFactory getInstance(Project project) { return ServiceManager.getService(project, LazyRangeMarkerFactory.class); } - public LazyRangeMarkerFactory(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) { - myProject = project; - - EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() { - @Override - public void beforeDocumentChange(DocumentEvent e) { - transformRangeMarkers(e); - } - - @Override - public void documentChanged(DocumentEvent e) { - transformRangeMarkers(e); - } - - private void transformRangeMarkers(@NotNull DocumentEvent e) { - Document document = e.getDocument(); - VirtualFile file = fileDocumentManager.getFile(document); - if (file == null) { - return; - } - - WeakList lazyMarkers = file.getUserData(LAZY_MARKERS_KEY); - if (lazyMarkers == null) { - return; - } - - List markers = lazyMarkers.toStrongList(); - List markersToRemove = null; - for (LazyMarker marker : markers) { - if (file.equals(marker.getFile()) && marker.documentChanged(document) != null) { - if (markersToRemove == null) { - markersToRemove = new SmartList(); - } - markersToRemove.add(marker); - } - } - if (markersToRemove != null) { - lazyMarkers.removeAll(markersToRemove); - } - } - }, project); - } - - private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) { - WeakList markers = file.getUserData(LAZY_MARKERS_KEY); - - if (markers == null) { - markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList()); - } - markers.add(marker); - } + @NotNull + public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset); @NotNull - public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public RangeMarker compute() { - // even for already loaded document do not create range marker yet - wait until it really needed when e.g. user clicked to jump to OpenFileDescriptor - final LazyMarker marker = new OffsetLazyMarker(file, offset); - addToLazyMarkersList(marker, file); - return marker; - } - }); - } - - @NotNull - public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public RangeMarker compute() { - final Document document = FileDocumentManager.getInstance().getCachedDocument(file); - if (document != null) { - final int offset = calculateOffset(myProject, file, document, line, column); - return document.createRangeMarker(offset, offset, persistent); - } - - final LazyMarker marker = new LineColumnLazyMarker(file, line, column); - addToLazyMarkersList(marker, file); - return marker; - } - }); - } - - private abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker { - private RangeMarker myDelegate; - private final VirtualFile myFile; - protected final int myInitialOffset; - - private LazyMarker(@NotNull VirtualFile file, int offset) { - myFile = file; - myInitialOffset = offset; - } - - @NotNull - public VirtualFile getFile() { - return myFile; - } - - @Nullable - protected final RangeMarker getOrCreateDelegate() { - if (myDelegate == null) { - Document document = FileDocumentManager.getInstance().getDocument(myFile); - if (document == null) { - return null; - } - myDelegate = createDelegate(myFile, document); - } - return myDelegate; - } - - @Nullable - protected final RangeMarker documentChanged(@NotNull Document document) { - if (myDelegate == null) { - myDelegate = createDelegate(myFile, document); - } - return myDelegate; - } - - @Nullable - protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document); - - @Override - @NotNull - public Document getDocument() { - RangeMarker delegate = getOrCreateDelegate(); - if (delegate == null) { - //noinspection ConstantConditions - return FileDocumentManager.getInstance().getDocument(myFile); - } - return delegate.getDocument(); - } - - @Override - public int getStartOffset() { - return myDelegate == null ? myInitialOffset : myDelegate.getStartOffset(); - } - - - @Override - public int getEndOffset() { - return myDelegate == null ? myInitialOffset : myDelegate.getEndOffset(); - } - - @Override - public boolean isValid() { - RangeMarker delegate = getOrCreateDelegate(); - return delegate != null && delegate.isValid(); - } - - @Override - public void setGreedyToLeft(boolean greedy) { - getOrCreateDelegate().setGreedyToLeft(greedy); - } - - @Override - public void setGreedyToRight(boolean greedy) { - getOrCreateDelegate().setGreedyToRight(greedy); - } - - @Override - public boolean isGreedyToRight() { - return getOrCreateDelegate().isGreedyToRight(); - } - - @Override - public boolean isGreedyToLeft() { - return getOrCreateDelegate().isGreedyToLeft(); - } - - @Override - public void dispose() { - RangeMarker delegate = getOrCreateDelegate(); - if (delegate != null) { - delegate.dispose(); - } - } - } - - private static class OffsetLazyMarker extends LazyMarker { - private OffsetLazyMarker(@NotNull VirtualFile file, int offset) { - super(file, offset); - } - - @Override - @NotNull - public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) { - final int offset = Math.min(myInitialOffset, document.getTextLength()); - return document.createRangeMarker(offset, offset); - } - } - - private class LineColumnLazyMarker extends LazyMarker { - private final int myLine; - private final int myColumn; - - private LineColumnLazyMarker(@NotNull VirtualFile file, int line, int column) { - super(file, -1); - myLine = line; - myColumn = column; - } - - @Override - @Nullable - public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) { - if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) { - return null; - } - - int offset = calculateOffset(myProject, file, document, myLine, myColumn); - return document.createRangeMarker(offset, offset); - } - - @Override - public int getStartOffset() { - getOrCreateDelegate(); - return super.getStartOffset(); - } - - @Override - public int getEndOffset() { - getOrCreateDelegate(); - return super.getEndOffset(); - } - } - - private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) { - int offset; - if (line < document.getLineCount()) { - final int lineStart = document.getLineStartOffset(line); - final int lineEnd = document.getLineEndOffset(line); - final CharSequence docText = document.getCharsSequence(); - final int tabSize = CodeStyleFacade.getInstance(project).getTabSize(file.getFileType()); - - offset = lineStart; - int col = 0; - while (offset < lineEnd && col < column) { - col += docText.charAt(offset) == '\t' ? tabSize : 1; - offset++; - } - } - else { - offset = document.getTextLength(); - } - return offset; - } - + public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent); } diff --git a/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java b/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java index 64aefa4c0977..b8e17ea3eded 100644 --- a/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java +++ b/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.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. @@ -115,7 +115,7 @@ public class DelayedDocumentWatcher { public void documentChanged(DocumentEvent event) { if (myDocumentSavingInProgress) { /** When {@link FileDocumentManager#saveAllDocuments} is called, - * {@link com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper} can change a document. + * {@link com.intellij.openapi.editor.impl.TrailingSpacesStripper} can change a document. * These needless 'documentChanged' events should be filtered out. */ return; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java new file mode 100644 index 000000000000..5a9c704173aa --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java @@ -0,0 +1,323 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.impl; + +import com.intellij.codeStyle.CodeStyleFacade; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.LazyRangeMarkerFactory; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.editor.event.DocumentAdapter; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.WeakList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class LazyRangeMarkerFactoryImpl extends LazyRangeMarkerFactory { + private final Project myProject; + private static final Key> LAZY_MARKERS_KEY = Key.create("LAZY_MARKERS_KEY"); + + public LazyRangeMarkerFactoryImpl(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) { + myProject = project; + + EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() { + @Override + public void beforeDocumentChange(DocumentEvent e) { + transformRangeMarkers(e); + } + + @Override + public void documentChanged(DocumentEvent e) { + transformRangeMarkers(e); + } + + private void transformRangeMarkers(@NotNull DocumentEvent e) { + Document document = e.getDocument(); + VirtualFile file = fileDocumentManager.getFile(document); + if (file == null) { + return; + } + + WeakList lazyMarkers = getMarkers(file); + if (lazyMarkers == null) { + return; + } + + List markers = lazyMarkers.toStrongList(); + for (LazyMarker marker : markers) { + if (file.equals(marker.getFile())) { + marker.getOrCreateDelegate(); + } + } + } + }, project); + } + + static WeakList getMarkers(@NotNull VirtualFile file) { + return file.getUserData(LazyRangeMarkerFactoryImpl.LAZY_MARKERS_KEY); + } + + private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) { + WeakList markers = getMarkers(file); + + if (markers == null) { + markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList()); + } + markers.add(marker); + } + + private static void removeFromLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) { + WeakList markers = getMarkers(file); + + if (markers != null) { + markers.remove(marker); + } + } + + @Override + @NotNull + public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public RangeMarker compute() { + // even for already loaded document do not create range marker yet - wait until it really needed when e.g. user clicked to jump to OpenFileDescriptor + final LazyMarker marker = new OffsetLazyMarker(file, offset); + addToLazyMarkersList(marker, file); + return marker; + } + }); + } + + @Override + @NotNull + public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public RangeMarker compute() { + final Document document = FileDocumentManager.getInstance().getCachedDocument(file); + if (document != null) { + final int offset = calculateOffset(myProject, file, document, line, column); + return document.createRangeMarker(offset, offset, persistent); + } + + final LazyMarker marker = new LineColumnLazyMarker(file, line, column); + addToLazyMarkersList(marker, file); + return marker; + } + }); + } + + abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker { + protected RangeMarker myDelegate; // the real range marker which is created only when document is opened, or (this) which means it's disposed + protected final VirtualFile myFile; + protected final int myInitialOffset; + + private LazyMarker(@NotNull VirtualFile file, int offset) { + myFile = file; + myInitialOffset = offset; + } + + boolean isDelegated() { + return myDelegate != null; + } + + @NotNull + public VirtualFile getFile() { + return myFile; + } + + @Nullable + protected final RangeMarker getOrCreateDelegate() { + if (myDelegate == null) { + Document document = FileDocumentManager.getInstance().getDocument(myFile); + if (document == null) { + return null; + } + myDelegate = createDelegate(myFile, document); + removeFromLazyMarkersList(this, myFile); + } + return isDisposed() ? null : myDelegate; + } + + @Nullable + protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document); + + @Override + @NotNull + public Document getDocument() { + RangeMarker delegate = getOrCreateDelegate(); + if (delegate == null) { + //noinspection ConstantConditions + return FileDocumentManager.getInstance().getDocument(myFile); + } + return delegate.getDocument(); + } + + @Override + public int getStartOffset() { + return myDelegate == null || isDisposed() ? myInitialOffset : myDelegate.getStartOffset(); + } + + public boolean isDisposed() { + return myDelegate == this; + } + + + @Override + public int getEndOffset() { + return myDelegate == null || isDisposed() ? myInitialOffset : myDelegate.getEndOffset(); + } + + @Override + public boolean isValid() { + RangeMarker delegate = getOrCreateDelegate(); + return delegate != null && !isDisposed() && delegate.isValid(); + } + + @Override + public void setGreedyToLeft(boolean greedy) { + getOrCreateDelegate().setGreedyToLeft(greedy); + } + + @Override + public void setGreedyToRight(boolean greedy) { + getOrCreateDelegate().setGreedyToRight(greedy); + } + + @Override + public boolean isGreedyToRight() { + return getOrCreateDelegate().isGreedyToRight(); + } + + @Override + public boolean isGreedyToLeft() { + return getOrCreateDelegate().isGreedyToLeft(); + } + + @Override + public void dispose() { + assert !isDisposed(); + RangeMarker delegate = myDelegate; + if (delegate == null) { + removeFromLazyMarkersList(this, myFile); + myDelegate = this; // mark of disposed marker + } + else { + delegate.dispose(); + } + } + } + + private static class OffsetLazyMarker extends LazyMarker { + private OffsetLazyMarker(@NotNull VirtualFile file, int offset) { + super(file, offset); + } + + @Override + public boolean isValid() { + RangeMarker delegate = myDelegate; + if (delegate == null) { + Document document = FileDocumentManager.getInstance().getDocument(myFile); + return document != null; + } + + return super.isValid(); + } + + @Override + @NotNull + public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) { + final int offset = Math.min(myInitialOffset, document.getTextLength()); + return document.createRangeMarker(offset, offset); + } + } + + private class LineColumnLazyMarker extends LazyMarker { + private final int myLine; + private final int myColumn; + + private LineColumnLazyMarker(@NotNull VirtualFile file, int line, int column) { + super(file, -1); + myLine = line; + myColumn = column; + } + + @Override + @Nullable + public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) { + if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) { + return null; + } + + int offset = calculateOffset(myProject, file, document, myLine, myColumn); + return document.createRangeMarker(offset, offset); + } + + @Override + public boolean isValid() { + RangeMarker delegate = myDelegate; + if (delegate == null) { + Document document = FileDocumentManager.getInstance().getDocument(myFile); + return document != null && (document.getTextLength() != 0 || myLine == 0 && myColumn == 0); + } + + return super.isValid(); + } + + @Override + public int getStartOffset() { + getOrCreateDelegate(); + return super.getStartOffset(); + } + + @Override + public int getEndOffset() { + getOrCreateDelegate(); + return super.getEndOffset(); + } + } + + private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) { + int offset; + if (line < document.getLineCount()) { + final int lineStart = document.getLineStartOffset(line); + final int lineEnd = document.getLineEndOffset(line); + final CharSequence docText = document.getCharsSequence(); + final int tabSize = CodeStyleFacade.getInstance(project).getTabSize(file.getFileType()); + + offset = lineStart; + int col = 0; + while (offset < lineEnd && col < column) { + col += docText.charAt(offset) == '\t' ? tabSize : 1; + offset++; + } + } + else { + offset = document.getTextLength(); + } + return offset; + } + +} diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java similarity index 97% rename from platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java rename to platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java index a5c477facfb3..05f587c124a2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.fileEditor.impl; +package com.intellij.openapi.editor.impl; import com.intellij.ide.DataManager; import com.intellij.injected.editor.DocumentWindow; @@ -23,7 +23,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; -import com.intellij.openapi.editor.impl.DocumentImpl; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter; import com.intellij.openapi.project.Project; @@ -37,11 +36,12 @@ import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import java.awt.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.Set; public final class TrailingSpacesStripper extends FileDocumentManagerAdapter { - public static final Key OVERRIDE_STRIP_TRAILING_SPACES_KEY = Key.create("OVERRIDE_TRIM_TRAILING_SPACES_KEY"); public static final Key OVERRIDE_ENSURE_NEWLINE_KEY = Key.create("OVERRIDE_ENSURE_NEWLINE_KEY"); @@ -61,7 +61,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter { strip(document); } - private void strip(final Document document) { + private void strip(@NotNull final Document document) { if (!document.isWritable()) return; FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); VirtualFile file = fileDocumentManager.getFile(document); @@ -149,7 +149,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter { ((DocumentImpl)document).clearLineModificationFlagsExcept(caretLines); } - public static boolean stripIfNotCurrentLine(Document document, boolean inChangedLinesOnly) { + public static boolean stripIfNotCurrentLine(@NotNull Document document, boolean inChangedLinesOnly) { if (document instanceof DocumentWindow) { document = ((DocumentWindow)document).getDelegate(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java index f396b1eed399..091ff1171157 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java @@ -37,6 +37,7 @@ import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.impl.EditorFactoryImpl; +import com.intellij.openapi.editor.impl.TrailingSpacesStripper; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl; diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 1f40bacf983c..1c616e736f40 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -190,7 +190,8 @@ - + diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java index 9f3484b35deb..d11847af849a 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java @@ -34,6 +34,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.Trinity; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.PsiDocumentManagerImpl; @@ -44,6 +45,7 @@ import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.Timings; import com.intellij.util.CommonProcessors; import com.intellij.util.ThrowableRunnable; +import com.intellij.util.containers.WeakList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -1077,13 +1079,13 @@ public class RangeMarkerTest extends LightPlatformTestCase { public void testRangeHighlighterLinesInRangeForLongLinePerformance() throws Exception { final int N = 50000; - Document document = EditorFactory.getInstance().createDocument(StringUtil.repeatSymbol('x', 2*N)); + Document document = EditorFactory.getInstance().createDocument(StringUtil.repeatSymbol('x', 2 * N)); final MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, ourProject, true); for (int i=0; i list = new ArrayList(); markupModel.processRangeHighlightersOverlappingWith(2, 9, new CommonProcessors.CollectProcessor(list)); - assertEquals(Arrays.asList(line,exact), list); + assertEquals(Arrays.asList(line, exact), list); + } + + public void testLazyRangeMarkers() { + psiFile = createFile("x.txt", "xxx"); + + LazyRangeMarkerFactoryImpl factory = (LazyRangeMarkerFactoryImpl)LazyRangeMarkerFactory.getInstance(getProject()); + VirtualFile virtualFile = psiFile.getVirtualFile(); + LazyRangeMarkerFactoryImpl.LazyMarker marker = (LazyRangeMarkerFactoryImpl.LazyMarker)factory.createRangeMarker(virtualFile, 0); + WeakList markers = LazyRangeMarkerFactoryImpl.getMarkers(virtualFile); + assertSame(marker, assertOneElement(markers)); + + assertFalse(marker.isDelegated()); + assertTrue(marker.isValid()); + assertEquals(0, marker.getStartOffset()); + assertFalse(marker.isDelegated()); + + marker.dispose(); + assertFalse(marker.isValid()); + assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile)); + + + marker = (LazyRangeMarkerFactoryImpl.LazyMarker)factory.createRangeMarker(virtualFile, 0); + assertFalse(marker.isDelegated()); + assertTrue(marker.isValid()); + assertEquals(0, marker.getStartOffset()); + assertFalse(marker.isDelegated()); + + Document document = marker.getDocument(); + document.insertString(2, "yyy"); + assertTrue(marker.isDelegated()); + assertTrue(marker.isValid()); + assertEquals(0, marker.getStartOffset()); + + assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile)); + marker.dispose(); + assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile)); } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java similarity index 98% rename from platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java rename to platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java index abfef7cf0657..285aadbef402 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.editor; +package com.intellij.openapi.editor.impl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper; import com.intellij.testFramework.LightPlatformCodeInsightTestCase; import org.jdom.Element; import org.jetbrains.annotations.NonNls; diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java index 24e4074ed4ee..3c1f96113532 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java @@ -35,10 +35,10 @@ import com.intellij.openapi.editor.actionSystem.EditorActionManager; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.DocumentImpl; import com.intellij.openapi.editor.impl.EditorImpl; +import com.intellij.openapi.editor.impl.TrailingSpacesStripper; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; -import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.ThrowableComputable;