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
This commit is contained in:
Dmitry Batrak
2014-02-21 16:48:27 +04:00
parent 65fc83821d
commit 99dab771cd
7 changed files with 88 additions and 22 deletions
@@ -0,0 +1,4 @@
class Foo {{
ret<caret>;
ret<caret>;
}}
@@ -0,0 +1,4 @@
class Foo {{
return<caret>;
return<caret>;
}}
@@ -0,0 +1,4 @@
class Foo {{
System.out.ap<caret>
System.out.ap<caret>
}}
@@ -0,0 +1,4 @@
class Foo {{
System.out.append(<caret>)
System.out.append(<caret>)
}}
@@ -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", """
@@ -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<LookupElement> items,
CompletionLookupArranger.StatisticsUpdate update) {
private static CompletionAssertions.WatchingInsertionContext insertItemHonorBlockSelection(final CompletionProgressIndicator indicator,
final LookupElement item,
final char completionChar,
final List<LookupElement> 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<CompletionAssertions.WatchingInsertionContext> contextRef = new Ref<CompletionAssertions.WatchingInsertionContext>();
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;
}
@@ -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);