From e822b4f8e69c24a2a54962a90ed1c2f57dc7d5cc Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 25 Jul 2011 18:55:42 +0200 Subject: [PATCH] undo of a completion finished by typing a character behaves first as if that character was just inserted into the document without any completion --- .../completion/JavaAutoPopupTest.groovy | 47 +++++++++---------- .../completion/CodeCompletionHandlerBase.java | 2 +- .../codeInsight/lookup/impl/TypedHandler.java | 45 ++++++++++++++++-- 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index f3313847ae27..d46121ca54ed 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -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 - } - } - """) - 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 {{ }}" - 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 {{ }}" + 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 {{ }}" - 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') diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 11888009a0c1..96d3162cf960 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -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(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java index 9cb628f1c290..2e6122aa4f21 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java @@ -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);