diff options
Diffstat (limited to 'platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java')
-rw-r--r-- | platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java | 263 |
1 files changed, 3 insertions, 260 deletions
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<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 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; - } - }); - } + public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset); @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); } |