completion during block selection to handle tab and backspace as expected
authorpeter <peter@jetbrains.com>
Wed, 18 Jan 2012 14:28:15 +0000 (15:28 +0100)
committerpeter <peter@jetbrains.com>
Wed, 18 Jan 2012 14:28:52 +0000 (15:28 +0100)
java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.java
platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java

index aab6671085cfeb300203be500d8b8c65e747788c..49fa6a2a352a7ad30682e6d8b7ffc718fc0e7ca0 100644 (file)
@@ -43,7 +43,6 @@ 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.openapi.util.Computable
 import com.intellij.psi.PsiFile
 import com.intellij.psi.PsiJavaFile
 import com.intellij.util.Consumer
@@ -1113,25 +1112,51 @@ public class UTest {
   }
 
   public void testBlockSelection() {
-    myFixture.configureByText "a.java", """
+    doTestBlockSelection """
+class Foo {{
+  <caret>tx;
+  tx;
+}}""", '\n', '''
+class Foo {{
+  toString()x;
+  toString()<caret>x;
+}}'''
+  }
+
+  public void testBlockSelectionTab() {
+    doTestBlockSelection """
+class Foo {{
+  <caret>tx;
+  tx;
+}}""", '\t', '''
+class Foo {{
+  toString();
+  toString()<caret>;
+}}'''
+  }
+
+  public void testBlockSelectionBackspace() {
+    doTestBlockSelection """
 class Foo {{
   <caret>t;
   t;
-}}"""
-    def caret = ApplicationManager.getApplication().runReadAction(new Computable<LogicalPosition>() {
-            public LogicalPosition compute() {
-              return myFixture.editor.offsetToLogicalPosition(myFixture.editor.caretModel.offset)
-            }});
-    edt { myFixture.editor.selectionModel.setBlockSelection(caret, new LogicalPosition(caret.line + 1, caret.column + 1)) }
-    type 'toStr'
-    assert lookup
-    type '\n'
-    myFixture.checkResult '''
+}}""", '\b\t', '''
 class Foo {{
   toString();
   toString()<caret>;
 }}'''
+  }
 
+  private doTestBlockSelection(final String textBefore, final String toType, final String textAfter) {
+    myFixture.configureByText "a.java", textBefore
+    edt {
+      def caret = myFixture.editor.offsetToLogicalPosition(myFixture.editor.caretModel.offset)
+      myFixture.editor.selectionModel.setBlockSelection(caret, new LogicalPosition(caret.line + 1, caret.column + 1))
+    }
+    type 'toStr'
+    assert lookup
+    type toType
+    myFixture.checkResult textAfter
     def start = myFixture.editor.selectionModel.blockStart
     def end = myFixture.editor.selectionModel.blockEnd
     assert start.line == end.line - 1
index 151916dddedd1c6a7420414c7ee1adf49b337dfd..6ff52c50a8373ff6a6c5871b101a04a8e0d45e67 100644 (file)
@@ -630,6 +630,9 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
 
     final Editor editor = indicator.getEditor();
 
+    final int caretOffset = editor.getCaretModel().getOffset();
+    final int idDelta = indicator.getIdentifierEndOffset() - caretOffset;
+
     WatchingInsertionContext context = null;
     if (editor.getSelectionModel().hasBlockSelection() && editor.getSelectionModel().getBlockSelectionEnds().length > 0) {
       List<RangeMarker> insertionPoints = new ArrayList<RangeMarker>();
@@ -640,7 +643,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
       List<RangeMarker> caretsAfter = new ArrayList<RangeMarker>();
       for (RangeMarker insertionPoint : insertionPoints) {
         if (insertionPoint.isValid()) {
-          context = insertItem(indicator, item, completionChar, items, update, editor, insertionPoint.getStartOffset());
+          context = insertItem(indicator, item, completionChar, items, update, editor, insertionPoint.getStartOffset(), idDelta);
           int offset = editor.getCaretModel().getOffset();
           caretsAfter.add(editor.getDocument().createRangeMarker(offset, offset));
         }
@@ -657,7 +660,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
       }
       
     } else {
-      context = insertItem(indicator, item, completionChar, items, update, editor, editor.getCaretModel().getOffset());
+      context = insertItem(indicator, item, completionChar, items, update, editor, caretOffset, idDelta);
     }
 
     final Runnable runnable = context.getLaterRunnable();
@@ -707,26 +710,26 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
                                                      final char completionChar,
                                                      List<LookupElement> items,
                                                      final CompletionLookupArranger.StatisticsUpdate update,
-                                                     final Editor editor, final int caretOffset) {
+                                                     final Editor editor, final int caretOffset, final int idDelta) {
     editor.getCaretModel().moveToOffset(caretOffset);
     final int initialStartOffset = caretOffset - item.getLookupString().length();
     assert initialStartOffset >= 0 : "negative startOffset: " + caretOffset + "; " + item.getLookupString();
+    final int idEndOffset = caretOffset + Math.max(idDelta, 0);
+    
     indicator.getOffsetMap().addOffset(CompletionInitializationContext.START_OFFSET, initialStartOffset);
     indicator.getOffsetMap().addOffset(CompletionInitializationContext.SELECTION_END_OFFSET, caretOffset);
+    indicator.getOffsetMap().addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, idEndOffset);
 
     final WatchingInsertionContext context = new WatchingInsertionContext(indicator, completionChar, items, editor);
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       @Override
       public void run() {
-        final int idEndOffset = Math.max(caretOffset, indicator.getIdentifierEndOffset());
-        indicator.getOffsetMap().addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, idEndOffset);
-        int selEnd = indicator.getSelectionEndOffset();
-        if (idEndOffset != selEnd && completionChar == Lookup.REPLACE_SELECT_CHAR) {
-          editor.getDocument().deleteString(selEnd, idEndOffset);
+        if (caretOffset != idEndOffset && completionChar == Lookup.REPLACE_SELECT_CHAR) {
+          editor.getDocument().deleteString(caretOffset, idEndOffset);
         }
 
-        assert context.getStartOffset() >= 0 : "stale startOffset: was " + initialStartOffset + "; selEnd=" + selEnd + "; idEnd=" + idEndOffset + "; file=" + context.getFile();
-        assert context.getTailOffset() >= 0 : "stale tail: was " + initialStartOffset + "; selEnd=" + selEnd + "; idEnd=" + idEndOffset + "; file=" + context.getFile();
+        assert context.getStartOffset() >= 0 : "stale startOffset: was " + initialStartOffset + "; selEnd=" + caretOffset + "; idEnd=" + idEndOffset + "; file=" + context.getFile();
+        assert context.getTailOffset() >= 0 : "stale tail: was " + initialStartOffset + "; selEnd=" + caretOffset + "; idEnd=" + idEndOffset + "; file=" + context.getFile();
 
         item.handleInsert(context);
         Project project = indicator.getProject();
index fc700195628428f1e99fa84049253a146af66d92..5087e8a4e0554e4d24c1565c67fc69274a061092 100644 (file)
@@ -45,7 +45,6 @@ public class BackspaceHandler extends EditorActionHandler {
     lookup.performGuardedChange(new Runnable() {
       @Override
       public void run() {
-        editor.getSelectionModel().removeSelection();
         handler.execute(editor, dataContext);
       }
     });
index 366d49120810263df568eedaa9c09a8919d3f2fb..f9949aa86f96ffffafdd2a67407f9c33c84473c9 100644 (file)
@@ -181,12 +181,19 @@ public abstract class LookupActionHandler extends EditorActionHandler {
     }
 
     @Override
-    protected void executeInLookup(LookupImpl lookup, DataContext context) {
+    protected void executeInLookup(final LookupImpl lookup, DataContext context) {
       if (!lookup.isCompletion()) {
         myOriginalHandler.execute(lookup.getEditor(), context);
         return;
       }
 
+      lookup.performGuardedChange(new Runnable() {
+        @Override
+        public void run() {
+          lookup.getEditor().getSelectionModel().removeSelection();
+        }
+      });
+
       BackspaceHandler.truncatePrefix(context, lookup, myOriginalHandler, lookup.getLookupStart() - 1);
     }
   }