From 99dab771cd3db1c9e7fe3651c7b819c84600a73a Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 21 Feb 2014 16:47:46 +0400 Subject: [PATCH] IDEA-80056 Column selection mode improvement completion behaviour improvements: * insert generated text into all carets' positions * apply post-completion actions (like parenthesis insertion) to all carets --- .../normal/MultiCaretSingleItemInsertion.java | 4 +++ .../MultiCaretSingleItemInsertion_after.java | 4 +++ .../normal/MulticaretMethodWithParen.java | 4 +++ .../MulticaretMethodWithParen_after.java | 4 +++ .../completion/NormalCompletionTest.groovy | 36 ++++++++++++++++++- .../completion/CodeCompletionHandlerBase.java | 25 +++++++++---- .../codeInsight/lookup/impl/LookupImpl.java | 33 +++++++++-------- 7 files changed, 88 insertions(+), 22 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/MultiCaretSingleItemInsertion.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/MultiCaretSingleItemInsertion_after.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/MulticaretMethodWithParen.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/MulticaretMethodWithParen_after.java diff --git a/java/java-tests/testData/codeInsight/completion/normal/MultiCaretSingleItemInsertion.java b/java/java-tests/testData/codeInsight/completion/normal/MultiCaretSingleItemInsertion.java new file mode 100644 index 000000000000..6c7981f4fbc6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MultiCaretSingleItemInsertion.java @@ -0,0 +1,4 @@ +class Foo {{ + ret; + ret; +}} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/MultiCaretSingleItemInsertion_after.java b/java/java-tests/testData/codeInsight/completion/normal/MultiCaretSingleItemInsertion_after.java new file mode 100644 index 000000000000..bed450b802e2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MultiCaretSingleItemInsertion_after.java @@ -0,0 +1,4 @@ +class Foo {{ + return; + return; +}} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/MulticaretMethodWithParen.java b/java/java-tests/testData/codeInsight/completion/normal/MulticaretMethodWithParen.java new file mode 100644 index 000000000000..a4bddd9cb46b --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MulticaretMethodWithParen.java @@ -0,0 +1,4 @@ +class Foo {{ + System.out.ap + System.out.ap +}} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/MulticaretMethodWithParen_after.java b/java/java-tests/testData/codeInsight/completion/normal/MulticaretMethodWithParen_after.java new file mode 100644 index 000000000000..46acfade83b6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MulticaretMethodWithParen_after.java @@ -0,0 +1,4 @@ +class Foo {{ + System.out.append() + System.out.append() +}} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index a511209092e9..fe527575da2b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiMethod import com.intellij.psi.codeStyle.CodeStyleSettingsManager import com.intellij.psi.codeStyle.CommonCodeStyleSettings +import com.intellij.testFramework.EditorTestUtil public class NormalCompletionTest extends LightFixtureCompletionTestCase { @Override @@ -874,6 +875,16 @@ public class ListUtils { doAntiTest() } + private void doMultiCaretTest() throws Exception { + EditorTestUtil.enableMultipleCarets() + try { + doTest() + } + finally { + EditorTestUtil.disableMultipleCarets() + } + } + private void doTest() throws Exception { configure() checkResult(); @@ -1365,6 +1376,29 @@ class Foo {{ }}''' } + public void testMulticaretSingleItemInsertion() { + doMultiCaretTest() + } + + public void testMulticaretMethodWithParen() { + doMultiCaretTest() + } + + public void testMulticaretTyping() { + EditorTestUtil.enableMultipleCarets() + try { + configure() + assert lookup + type('p') + assert lookup + type('\n') + checkResult() + } + finally { + EditorTestUtil.disableMultipleCarets() + } + } + public void "test complete lowercase class name"() { myFixture.addClass("package foo; public class myClass {}") myFixture.configureByText "a.java", """ 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 1aa29cc14ee3..aa32ce31a646 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -574,11 +574,11 @@ public class CodeCompletionHandlerBase { } - private static CompletionAssertions.WatchingInsertionContext insertItemHonorBlockSelection(CompletionProgressIndicator indicator, - LookupElement item, - char completionChar, - List items, - CompletionLookupArranger.StatisticsUpdate update) { + private static CompletionAssertions.WatchingInsertionContext insertItemHonorBlockSelection(final CompletionProgressIndicator indicator, + final LookupElement item, + final char completionChar, + final List items, + final CompletionLookupArranger.StatisticsUpdate update) { final Editor editor = indicator.getEditor(); final int caretOffset = editor.getCaretModel().getOffset(); @@ -586,6 +586,7 @@ public class CodeCompletionHandlerBase { if (idEndOffset < 0) { idEndOffset = CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset); } + final int idEndOffsetDelta = idEndOffset - caretOffset; CompletionAssertions.WatchingInsertionContext context = null; if (editor.getSelectionModel().hasBlockSelection() && editor.getSelectionModel().getBlockSelectionEnds().length > 0) { @@ -622,7 +623,17 @@ public class CodeCompletionHandlerBase { } } else { - context = insertItem(indicator, item, completionChar, items, update, editor, caretOffset, idEndOffset); + final Ref contextRef = new Ref(); + editor.getCaretModel().runForEachCaret(new CaretAction() { + @Override + public void perform(Caret caret) { + CompletionAssertions.WatchingInsertionContext currentContext = insertItem(indicator, item, completionChar, items, update, editor, caret.getOffset(), caret.getOffset() + idEndOffsetDelta); + if (caret == editor.getCaretModel().getPrimaryCaret()) { + contextRef.set(currentContext); + } + } + }); + context = contextRef.get(); } return context; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index b92155067b27..26115d4b307e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -678,9 +678,9 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable } private void insertLookupString(LookupElement item, final int prefix) { - Document document = myEditor.getDocument(); + final Document document = myEditor.getDocument(); - String lookupString = getCaseCorrectedLookupString(item); + final String lookupString = getCaseCorrectedLookupString(item); if (myEditor.getSelectionModel().hasBlockSelection()) { LogicalPosition blockStart = myEditor.getSelectionModel().getBlockStart(); @@ -710,20 +710,25 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable myEditor.getSelectionModel().setBlockSelection(start, end); myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine, end.column)); } else { - EditorModificationUtil.deleteSelectedText(myEditor); - final int caretOffset = myEditor.getCaretModel().getOffset(); - int lookupStart = caretOffset - prefix; + myEditor.getCaretModel().runForEachCaret(new CaretAction() { + @Override + public void perform(Caret caret) { + EditorModificationUtil.deleteSelectedText(myEditor); + final int caretOffset = myEditor.getCaretModel().getOffset(); + int lookupStart = caretOffset - prefix; - int len = document.getTextLength(); - LOG.assertTrue(lookupStart >= 0 && lookupStart <= len, - "ls: " + lookupStart + " caret: " + caretOffset + " prefix:" + prefix + " doc: " + len); - LOG.assertTrue(caretOffset >= 0 && caretOffset <= len, "co: " + caretOffset + " doc: " + len); + int len = document.getTextLength(); + LOG.assertTrue(lookupStart >= 0 && lookupStart <= len, + "ls: " + lookupStart + " caret: " + caretOffset + " prefix:" + prefix + " doc: " + len); + LOG.assertTrue(caretOffset >= 0 && caretOffset <= len, "co: " + caretOffset + " doc: " + len); - document.replaceString(lookupStart, caretOffset, lookupString); + document.replaceString(lookupStart, caretOffset, lookupString); - int offset = lookupStart + lookupString.length(); - myEditor.getCaretModel().moveToOffset(offset); - myEditor.getSelectionModel().removeSelection(); + int offset = lookupStart + lookupString.length(); + myEditor.getCaretModel().moveToOffset(offset); + myEditor.getSelectionModel().removeSelection(); + } + }); } myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);