range markers optimisations: create fewer markers in OpenFileDescriptor and LazyMarkerFactory

This commit is contained in:
Alexey Kudravtsev
2014-07-23 14:41:52 +04:00
parent d948e9bd56
commit 846e6be9f9
10 changed files with 384 additions and 278 deletions
@@ -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<Integer> caretOffsets) {
@@ -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<WeakList<LazyMarker>> 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<LazyMarker> lazyMarkers = file.getUserData(LAZY_MARKERS_KEY);
if (lazyMarkers == null) {
return;
}
List<LazyMarker> markers = lazyMarkers.toStrongList();
List<LazyMarker> markersToRemove = null;
for (LazyMarker marker : markers) {
if (file.equals(marker.getFile()) && marker.documentChanged(document) != null) {
if (markersToRemove == null) {
markersToRemove = new SmartList<LazyMarker>();
}
markersToRemove.add(marker);
}
}
if (markersToRemove != null) {
lazyMarkers.removeAll(markersToRemove);
}
}
}, project);
}
private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
WeakList<LazyMarker> markers = file.getUserData(LAZY_MARKERS_KEY);
if (markers == null) {
markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList<LazyMarker>());
}
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<RangeMarker>() {
@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<RangeMarker>() {
@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);
}
@@ -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;
@@ -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<WeakList<LazyMarker>> 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<LazyMarker> lazyMarkers = getMarkers(file);
if (lazyMarkers == null) {
return;
}
List<LazyMarker> markers = lazyMarkers.toStrongList();
for (LazyMarker marker : markers) {
if (file.equals(marker.getFile())) {
marker.getOrCreateDelegate();
}
}
}
}, project);
}
static WeakList<LazyMarker> getMarkers(@NotNull VirtualFile file) {
return file.getUserData(LazyRangeMarkerFactoryImpl.LAZY_MARKERS_KEY);
}
private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
WeakList<LazyMarker> markers = getMarkers(file);
if (markers == null) {
markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList<LazyMarker>());
}
markers.add(marker);
}
private static void removeFromLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
WeakList<LazyMarker> 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<RangeMarker>() {
@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<RangeMarker>() {
@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;
}
}
@@ -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<String> OVERRIDE_STRIP_TRAILING_SPACES_KEY = Key.create("OVERRIDE_TRIM_TRAILING_SPACES_KEY");
public static final Key<Boolean> 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();
}
@@ -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;
@@ -190,7 +190,8 @@
<projectService serviceInterface="com.intellij.openapi.vcs.VcsFileListenerContextHelper"
serviceImplementation="com.intellij.openapi.vcs.VcsFileListenerContextHelper"/>
<projectService serviceImplementation="com.intellij.openapi.editor.LazyRangeMarkerFactory"/>
<projectService serviceInterface="com.intellij.openapi.editor.LazyRangeMarkerFactory"
serviceImplementation="com.intellij.openapi.editor.impl.LazyRangeMarkerFactoryImpl"/>
<!-- General -->
<applicationConfigurable groupId="appearance" key="title.general" bundle="messages.IdeBundle" id="preferences.general" instance="com.intellij.ide.GeneralSettingsConfigurable"/>
@@ -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<N-1;i++) {
markupModel.addRangeHighlighter(2*i, 2*i+1, 0, null, HighlighterTargetArea.EXACT_RANGE);
}
markupModel.addRangeHighlighter(N/2, N/2+1, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
markupModel.addRangeHighlighter(N / 2, N / 2 + 1, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
PlatformTestUtil.startPerformanceTest("slow highlighters lookup", (int)(N*Math.log(N)/1000), new ThrowableRunnable() {
@Override
@@ -1107,6 +1109,42 @@ public class RangeMarkerTest extends LightPlatformTestCase {
RangeHighlighter line = markupModel.addRangeHighlighter(4, 5, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
List<RangeHighlighter> list = new ArrayList<RangeHighlighter>();
markupModel.processRangeHighlightersOverlappingWith(2, 9, new CommonProcessors.CollectProcessor<RangeHighlighter>(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<LazyRangeMarkerFactoryImpl.LazyMarker> 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));
}
}
@@ -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;
@@ -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;