undo of a completion finished by typing a character behaves first as if that character was just inserted into the document without any completion

This commit is contained in:
peter
2011-07-25 20:00:29 +02:00
parent cb7213781b
commit e822b4f8e6
3 changed files with 64 additions and 30 deletions
@@ -25,15 +25,19 @@ import com.intellij.codeInsight.template.TemplateManager
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.ide.DataManager
import com.intellij.ide.ui.UISettings
import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.IdeActions
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.command.impl.CurrentEditorProvider
import com.intellij.openapi.command.impl.UndoManagerImpl
import com.intellij.openapi.command.undo.UndoManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.actionSystem.EditorActionManager
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.LoadingOrder
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.progress.ProgressManager
import com.intellij.psi.PsiFile
@@ -216,26 +220,6 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
"""
}
public void _testHideAutopopupIfItContainsExactMatch() {
myFixture.configureByText("a.java", """
class Foo {
String foo() {
int abcd;
int abcde;
int abcdefg;
ab<caret>
}
}
""")
type 'c'
assert lookup
type 'd'
assert !lookup
type 'e'
assert !lookup
type 'f'
assert lookup
}
public void testFocusInJavadoc() {
myFixture.configureByText("a.java", """
@@ -844,10 +828,24 @@ class LiveComplete {
assert myFixture.file.text.contains("innerThing();")
}
public void _testCharSelectionUndo() {
myFixture.configureByText "a.java", "class Foo {{ <caret> }}"
def editor;
private FileEditor openEditorForUndo() {
FileEditor editor;
edt { editor = FileEditorManager.getInstance(project).openFile(myFixture.file.virtualFile, false)[0] }
def manager = (UndoManagerImpl) UndoManager.getInstance(project)
def old = manager.editorProvider
manager.editorProvider = new CurrentEditorProvider() {
@Override
public FileEditor getCurrentEditor() {
return editor;
}
};
disposeOnTearDown ({ manager.editorProvider = old } as Disposable)
return editor
}
public void testCharSelectionUndo() {
myFixture.configureByText "a.java", "class Foo {{ <caret> }}"
def editor = openEditorForUndo();
type('ArrStoExce.')
edt { UndoManager.getInstance(project).undo(editor) }
assert myFixture.editor.document.text.contains('ArrStoExce.')
@@ -855,8 +853,7 @@ class LiveComplete {
public void testAutopopupTypingUndo() {
myFixture.configureByText "a.java", "class Foo {{ <caret> }}"
def editor;
edt { editor = FileEditorManager.getInstance(project).openFile(myFixture.file.virtualFile, false)[0] }
def editor = openEditorForUndo();
type 'aioobeeee'
edt { UndoManager.getInstance(project).undo(editor) }
assert !myFixture.editor.document.text.contains('aioo')
@@ -672,7 +672,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
}
}
private static Runnable rememberDocumentState(final Editor editor) {
public static Runnable rememberDocumentState(final Editor editor) {
final String documentText = editor.getDocument().getText();
final int caret = editor.getCaretModel().getOffset();
final int selStart = editor.getSelectionModel().getSelectionStart();
@@ -17,6 +17,7 @@
package com.intellij.codeInsight.lookup.impl;
import com.intellij.codeInsight.completion.CodeCompletionFeatures;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionProgressIndicator;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
@@ -28,6 +29,8 @@ import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.template.impl.editorActions.TypedActionHandlerBase;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.CommandProcessorEx;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
@@ -46,6 +49,7 @@ public class TypedHandler extends TypedActionHandlerBase {
super(originalHandler);
}
@SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
public void execute(@NotNull final Editor editor, final char charTyped, @NotNull final DataContext dataContext){
assert !inside;
inside = true;
@@ -57,7 +61,7 @@ public class TypedHandler extends TypedActionHandlerBase {
}
if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), editor.getProject())) {
return;
return;
}
final CharFilter.Result result = getLookupAction(charTyped, lookup);
@@ -92,9 +96,13 @@ public class TypedHandler extends TypedActionHandlerBase {
if (result == CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP && lookup.isFocused()) {
LookupElement item = lookup.getCurrentItem();
if (item != null){
inside = false;
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_FINISH_BY_DOT_ETC);
lookup.finishLookup(charTyped);
((CommandProcessorEx)CommandProcessor.getInstance()).enterModal();
try {
finishLookup(editor, charTyped, lookup);
}
finally {
((CommandProcessorEx)CommandProcessor.getInstance()).leaveModal();
}
return;
}
}
@@ -107,6 +115,35 @@ public class TypedHandler extends TypedActionHandlerBase {
}
}
private static void finishLookup(final Editor editor, final char charTyped, final LookupImpl lookup) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_FINISH_BY_DOT_ETC);
final boolean charInserted = !editor.getSelectionModel().hasSelection() && !editor.getSelectionModel().hasBlockSelection();
final Runnable restore = CodeCompletionHandlerBase.rememberDocumentState(editor);
if (charInserted) {
CommandProcessor.getInstance().executeCommand(editor.getProject(), new Runnable() {
@Override
public void run() {
lookup.performGuardedChange(new Runnable() {
public void run() {
EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, String.valueOf(charTyped), true);
}
});
}
}, null, "Just insert the completion char");
}
inside = false;
CommandProcessor.getInstance().executeCommand(editor.getProject(), new Runnable() {
@Override
public void run() {
if (charInserted) {
lookup.performGuardedChange(restore);
}
lookup.finishLookup(charTyped);
}
}, null, "Undo inserting the completion char and select the item");
}
static CharFilter.Result getLookupAction(final char charTyped, final LookupImpl lookup) {
final CharFilter.Result filtersDecision = getFiltersDecision(charTyped, lookup);