This commit is contained in:
Alexey Kudravtsev
2010-08-25 14:05:28 +04:00
parent 6dd69cde46
commit 8fc27f7cf2
12 changed files with 162 additions and 100 deletions

View File

@@ -29,6 +29,7 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.TypedAction;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.TextEditor;
@@ -74,11 +75,11 @@ public abstract class CodeInsightTestCase extends PsiTestCase {
protected Editor createEditor(VirtualFile file) {
final FileEditorManager instance = FileEditorManager.getInstance(myProject);
if (file.getFileType().isBinary()) {
return null;
}
if (file.getFileType().isBinary()) return null;
return instance.openTextEditor(new OpenFileDescriptor(myProject, file, 0), false);
Editor editor = instance.openTextEditor(new OpenFileDescriptor(myProject, file, 0), false);
((EditorImpl)editor).setCaretActive();
return editor;
}
protected void tearDown() throws Exception {
@@ -443,7 +444,7 @@ public abstract class CodeInsightTestCase extends PsiTestCase {
checkResultByFile(filePath, false);
}
protected void checkResultByFile(String filePath, boolean stripTrailingSpaces) throws Exception {
protected void checkResultByFile(@NonNls String filePath, boolean stripTrailingSpaces) throws Exception {
getProject().getComponent(PostprocessReformattingAspect.class).doPostponedFormatting();
if (stripTrailingSpaces) {
((DocumentEx)myEditor.getDocument()).stripTrailingSpaces(false);

View File

@@ -28,6 +28,7 @@ import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.impl.IntentionHintComponent;
import com.intellij.concurrency.Job;
import com.intellij.ide.PowerSaveMode;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -222,7 +223,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
public void updateVisibleHighlighters(@NotNull Editor editor) {
ApplicationManager.getApplication().assertIsDispatchThread();
if (!myUpdateByTimerEnabled) return;
//if (ApplicationManager.getApplication().isUnitTestMode()) return;
if (editor instanceof EditorWindow) editor = ((EditorWindow)editor).getDelegate();
final TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor);
BackgroundEditorHighlighter highlighter = textEditor.getBackgroundHighlighter();

View File

@@ -434,8 +434,8 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
return new RangeMarkerWindow(this, (RangeMarkerEx)hostMarker);
}
public void stripTrailingSpaces(final boolean inChangedLinesOnly) {
myDelegate.stripTrailingSpaces(inChangedLinesOnly);
public boolean stripTrailingSpaces(final boolean inChangedLinesOnly) {
return myDelegate.stripTrailingSpaces(inChangedLinesOnly);
}
public void setStripTrailingSpacesEnabled(final boolean isEnabled) {

View File

@@ -295,6 +295,11 @@ public class EditorWindow extends UserDataHolderBase implements EditorEx {
return new LogicalPosition(lineNumber, column);
}
@Override
public boolean isCaretActive() {
return myDelegate.isCaretActive();
}
@NotNull
public LogicalPosition xyToLogicalPosition(@NotNull final Point p) {
assert isValid();

View File

@@ -23,7 +23,10 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface DocumentEx extends Document {
void stripTrailingSpaces(boolean inChangedLinesOnly);
/**
* @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret being in the way
*/
boolean stripTrailingSpaces(boolean inChangedLinesOnly);
void setStripTrailingSpacesEnabled(boolean isEnabled);
@NotNull LineIterator createLineIterator();

View File

@@ -21,7 +21,6 @@ import com.intellij.ide.DeleteProvider;
import com.intellij.ide.PasteProvider;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldingModel;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
@@ -34,7 +33,6 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeListener;
@@ -137,4 +135,9 @@ public interface EditorEx extends Editor {
LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visiblePos, boolean softWrapAware);
@NotNull LogicalPosition offsetToLogicalPosition(int offset, boolean softWrapAware);
/**
* @return true if caret cursor is blinking in this editor
*/
boolean isCaretActive();
}

View File

@@ -38,6 +38,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -137,52 +138,54 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
isStripTrailingSpacesEnabled = isEnabled;
}
public void stripTrailingSpaces(boolean inChangedLinesOnly) {
Editor[] editors = EditorFactory.getInstance().getEditors(this, null);
VisualPosition[] visualCarets = new VisualPosition[editors.length];
int[] caretLines = new int[editors.length];
for (int i = 0; i < editors.length; i++) {
visualCarets[i] = editors[i].getCaretModel().getVisualPosition();
caretLines[i] = editors[i].getCaretModel().getLogicalPosition().line;
public boolean stripTrailingSpaces(boolean inChangedLinesOnly) {
if (!isStripTrailingSpacesEnabled) {
return true;
}
if (!isStripTrailingSpacesEnabled) {
return;
}
Editor editor = ContainerUtil.find(EditorFactory.getInstance().getEditors(this), new Condition<Editor>() {
@Override
public boolean value(Editor editor) {
return ((EditorEx)editor).isCaretActive();
}
});
// when virtual space enabled, we can strip whitespace anywhere
boolean isVirtualSpaceEnabled = editor == null || editor.getSettings().isVirtualSpace();
VisualPosition visualCaret = editor == null ? null : editor.getCaretModel().getVisualPosition();
int caretLine = editor == null ? -1 : editor.getCaretModel().getLogicalPosition().line;
boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode();
lines:
for (int i = 0; i < myLineSet.getLineCount(); i++) {
if (!isTestMode) {
for (int caretLine : caretLines) {
if (caretLine == i) continue lines;
}
}
if (!inChangedLinesOnly || myLineSet.isModified(i)) {
int start = -1;
int lineEnd = myLineSet.getLineEnd(i) - myLineSet.getSeparatorLength(i);
int lineStart = myLineSet.getLineStart(i);
CharSequence text = myText.getCharArray();
for (int offset = lineEnd - 1; offset >= lineStart; offset--) {
char c = text.charAt(offset);
if (c != ' ' && c != '\t') {
break;
}
start = offset;
}
if (start != -1) {
deleteString(start, lineEnd);
}
}
boolean markAsNeedsStrippingLater = false;
for (int line = 0; line < myLineSet.getLineCount(); line++) {
if (inChangedLinesOnly && !myLineSet.isModified(line)) continue;
int start = -1;
int lineEnd = myLineSet.getLineEnd(line) - myLineSet.getSeparatorLength(line);
int lineStart = myLineSet.getLineStart(line);
CharSequence text = myText.getCharArray();
for (int offset = lineEnd - 1; offset >= lineStart; offset--) {
char c = text.charAt(offset);
if (c != ' ' && c != '\t') {
break;
}
if (!ShutDownTracker.isShutdownHookRunning()) {
for (int i = 0; i < editors.length; i++) {
editors[i].getCaretModel().moveToVisualPosition(visualCarets[i]);
start = offset;
}
if (start == -1) continue;
if (!isTestMode && !isVirtualSpaceEnabled && caretLine == line) {
// mark this as a document that needs stripping later
// otherwise the caret would jump madly
markAsNeedsStrippingLater = true;
}
else {
deleteString(start, lineEnd);
}
}
if (!ShutDownTracker.isShutdownHookRunning() && editor != null) {
editor.getCaretModel().moveToVisualPosition(visualCaret);
}
return !markAsNeedsStrippingLater;
}
public void setReadOnly(boolean isReadOnly) {
@@ -530,8 +533,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
return myText.toString();
}
@NotNull
@Override
public String getText(TextRange range) {
public String getText(@NotNull TextRange range) {
assertReadAccessToDocumentsAllowed();
return myText.substring(range.getStartOffset(), range.getEndOffset()).toString();
}

View File

@@ -77,6 +77,7 @@ import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import javax.swing.Timer;
@@ -244,7 +245,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
ourCaretBlinkingCommand.start();
}
public EditorImpl(Document document, boolean viewer, Project project) {
EditorImpl(@NotNull Document document, boolean viewer, Project project) {
myProject = project;
myDocument = (DocumentImpl)document;
myScheme = new MyColorSchemeDelegate();
@@ -1018,6 +1019,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return new LogicalPosition(line, column);
}
@Override
public boolean isCaretActive() {
return myCaretCursor.isActive();
}
@TestOnly
public void setCaretActive() {
myCaretCursor.setActive();
}
public int offsetToVisualLine(int offset) {
int line = calcLogicalLineNumber(offset);
return logicalToVisualLine(line);
@@ -3398,6 +3409,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return myIsShown;
}
}
public void setActive() {
synchronized (ourCaretBlinkingCommand) {
myIsShown = true;
}
}
private void passivate() {
synchronized (ourCaretBlinkingCommand) {

View File

@@ -53,6 +53,7 @@ import com.intellij.ui.UIBundle;
import com.intellij.util.EventDispatcher;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
@@ -73,16 +74,16 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
public static final Key<Reference<Document>> DOCUMENT_KEY = Key.create("DOCUMENT_KEY");
private static final Key<VirtualFile> FILE_KEY = Key.create("FILE_KEY");
private final Set<Document> myUnsavedDocuments = new HashSet<Document>();
private final Set<Document> myUnsavedDocuments = new THashSet<Document>();
private final EditReadOnlyListener myReadOnlyListener = new MyEditReadOnlyListener();
private final EventDispatcher<FileDocumentSynchronizationVetoListener> myVetoDispatcher = EventDispatcher.create(
FileDocumentSynchronizationVetoListener.class);
private final EventDispatcher<FileDocumentSynchronizationVetoListener> myVetoDispatcher = EventDispatcher.create(FileDocumentSynchronizationVetoListener.class);
private final VirtualFileManager myVirtualFileManager;
private final MessageBus myBus;
private static final Object lock = new Object();
private final TrailingSpacesStripper myTrailingSpacesStripper;
public FileDocumentManagerImpl(VirtualFileManager virtualFileManager) {
myVirtualFileManager = virtualFileManager;
@@ -90,7 +91,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
myVirtualFileManager.addVirtualFileListener(this);
myBus = ApplicationManager.getApplication().getMessageBus();
myBus.connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, new TrailingSpacesStripper());
myTrailingSpacesStripper = new TrailingSpacesStripper(myBus);
}
@NotNull
@@ -183,10 +184,11 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
throw new RuntimeException("This method is only for test mode!");
}
ApplicationManager.getApplication().assertWriteAccessAllowed();
if (myUnsavedDocuments.size() > 0) {
if (!myUnsavedDocuments.isEmpty()) {
myUnsavedDocuments.clear();
fireUnsavedDocumensDropped();
}
myTrailingSpacesStripper.dropAll();
}
public void saveAllDocuments() {
@@ -194,7 +196,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
if (myUnsavedDocuments.isEmpty()) return;
HashSet<Document> failedToSave = new HashSet<Document>();
Set<Document> failedToSave = new THashSet<Document>();
while (true) {
final Document[] unsavedDocuments = getUnsavedDocuments();
@@ -224,7 +226,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
);
}
private void _saveDocument(final Document document) {
private void _saveDocument(@NotNull final Document document) {
boolean committed = false;
try {
VirtualFile file = getFile(document);
@@ -442,12 +444,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
}
};
//if (!ApplicationManager.getApplication().isUnitTestMode()){
// LaterInvocator.invokeLater(askReloadRunnable);
//}
//else{
askReloadRunnable.run();
//}
}
else {
reloadFromDisk(document);
@@ -486,17 +483,6 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
);
}
}, UIBundle.message("file.cache.conflict.action"), null);
//ApplicationManager.getApplication().runWriteAction(
// new ExternalChangeAction() {
// public void run() {
// boolean wasWritable = document.isWritable();
// DocumentEx documentEx = (DocumentEx)document;
// documentEx.setReadOnly(false);
// documentEx.replaceText(LoadTextUtil.loadText(file), file.getModificationStamp());
// documentEx.setReadOnly(!wasWritable);
// }
// }
//);
myUnsavedDocuments.remove(document);
@@ -543,12 +529,10 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
}
}
});
//int option = Messages.showYesNoDialog(message, "File Cache Conflict", Messages.getQuestionIcon());
builder.setTitle(UIBundle.message("file.cache.conflict.dialog.title"));
builder.setButtonsAlignment(SwingConstants.CENTER);
builder.setHelpId("reference.dialogs.fileCacheConflict");
return builder.show() == 0;
//return option == 0;
}
protected void reportErrorOnSave(final IOException e) {

View File

@@ -15,15 +15,42 @@
*/
package com.intellij.openapi.fileEditor.impl;
import com.intellij.AppTopics;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
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.FileDocumentManagerAdapter;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.text.CharArrayUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.TestOnly;
public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
public void beforeDocumentSaving(final Document document) {
import java.util.Set;
public final class TrailingSpacesStripper {
private final Set<DocumentEx> myDocumentsToStripLater = new THashSet<DocumentEx>();
public TrailingSpacesStripper(MessageBus bus) {
bus.connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
@Override
public void beforeAllDocumentsSaving() {
Set<DocumentEx> documentsToStrip = new THashSet<DocumentEx>(myDocumentsToStripLater);
myDocumentsToStripLater.clear();
for (DocumentEx documentEx : documentsToStrip) {
strip(documentEx);
}
}
@Override
public void beforeDocumentSaving(Document document) {
strip(document);
}
});
}
private void strip(final Document document) {
if (!document.isWritable()) return;
final EditorSettingsExternalizable settings = EditorSettingsExternalizable.getInstance();
@@ -33,30 +60,44 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
final boolean ensureEOL = settings.isEnsureNewLineAtEOF();
if (!doStrip && !ensureEOL) return;
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
if (doStrip) {
final boolean inChangedLinesOnly = !settings.getStripTrailingSpaces().equals(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
((DocumentEx)document).stripTrailingSpaces(inChangedLinesOnly);
}
if (ensureEOL) {
final int lines = document.getLineCount();
if (lines > 0) {
int start = document.getLineStartOffset(lines - 1);
int end = document.getLineEndOffset(lines - 1);
if (start != end) {
CharSequence content = document.getCharsSequence();
if (CharArrayUtil.containsOnlyWhiteSpaces(content.subSequence(start, end))) {
document.deleteString(start, end);
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
public void run() {
if (doStrip) {
final boolean inChangedLinesOnly =
!settings.getStripTrailingSpaces().equals(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
DocumentEx ex = (DocumentEx)document;
boolean success = ex.stripTrailingSpaces(inChangedLinesOnly);
if (!success) {
myDocumentsToStripLater.add(ex);
}
else {
document.insertString(end, "\n");
}
if (ensureEOL) {
final int lines = document.getLineCount();
if (lines > 0) {
int start = document.getLineStartOffset(lines - 1);
int end = document.getLineEndOffset(lines - 1);
if (start != end) {
CharSequence content = document.getCharsSequence();
if (CharArrayUtil.containsOnlyWhiteSpaces(content.subSequence(start, end))) {
document.deleteString(start, end);
}
else {
document.insertString(end, "\n");
}
}
}
}
}
}
});
}
});
}
@TestOnly
public void dropAll() {
myDocumentsToStripLater.clear();
}
}

View File

@@ -170,7 +170,8 @@ public class MockDocument implements DocumentEx {
myUserData.put(key, value);
}
public void stripTrailingSpaces(boolean inChangedLinesOnly) {
public boolean stripTrailingSpaces(boolean inChangedLinesOnly) {
return true;
}
public void setStripTrailingSpacesEnabled(boolean isEnabled) {

View File

@@ -29,6 +29,7 @@ import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.ex.DocumentEx;
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.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -163,8 +164,10 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest
}
}
private static Editor createEditor(VirtualFile file) {
return FileEditorManager.getInstance(getProject()).openTextEditor(new OpenFileDescriptor(getProject(), file, 0), false);
protected static Editor createEditor(VirtualFile file) {
Editor editor = FileEditorManager.getInstance(getProject()).openTextEditor(new OpenFileDescriptor(getProject(), file, 0), false);
((EditorImpl)editor).setCaretActive();
return editor;
}
private static void setupFileEditorAndDocument(final String fileName, String fileText) throws IOException {