Code completion: '=' char supported for all items + it inserts spaces around '='

This commit is contained in:
Valentin Kipyatkov
2014-11-14 14:06:16 +03:00
parent 08f43dcbf8
commit 7b7e992515
10 changed files with 70 additions and 23 deletions
@@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor
public class KotlinCompletionCharFilter() : CharFilter() {
class object {
public val ACCEPT_OPENING_BRACE: Key<Boolean> = Key("KotlinCompletionCharFilter.ACCEPT_OPENNING_BRACE")
public val ACCEPT_EQ: Key<Boolean> = Key("KotlinCompletionCharFilter.ACCEPT_EQ")
public val SELECTED_ITEM_PREFIX: Key<String> = Key("KotlinCompletionCharFilter.SELECTED_ITEM_PREFIX")
}
@@ -61,14 +60,7 @@ public class KotlinCompletionCharFilter() : CharFilter() {
Result.HIDE_LOOKUP
}
'=' -> {
if (currentItem != null && currentItem.getUserData(ACCEPT_EQ) ?: false)
Result.SELECT_ITEM_AND_FINISH_LOOKUP
else
Result.HIDE_LOOKUP //TODO: why not for others?
}
',', ' ', '(' -> Result.SELECT_ITEM_AND_FINISH_LOOKUP
',', ' ', '(', '=' -> Result.SELECT_ITEM_AND_FINISH_LOOKUP
else -> CharFilter.Result.HIDE_LOOKUP
}
@@ -94,17 +94,25 @@ class LookupElementsCollector(private val prefixMatcher: PrefixMatcher, private
override fun handleInsert(context: InsertionContext) {
getDelegate().handleInsert(context)
if (context.getCompletionChar() == ',' && context.shouldAddCompletionChar()) {
val insertedText = context.getDocument().getText(TextRange(context.getStartOffset(), context.getTailOffset()))
if (insertedText != getUserData(KotlinCompletionCharFilter.SELECTED_ITEM_PREFIX)) { // avoid insertion of space after comma if we have typed the whole text to insert already
WithTailInsertHandler.commaTail().postHandleInsert(context, getDelegate())
if (context.shouldAddCompletionChar() && !isJustTyping(context, this)) {
val handler = when (context.getCompletionChar()) {
',' -> WithTailInsertHandler.commaTail()
'=' -> WithTailInsertHandler.eqTail()
else -> null
}
handler?.postHandleInsert(context, getDelegate())
}
}
})
}
}
// used to avoid insertion of spaces before/after ',', '=' on just typing
private fun isJustTyping(context: InsertionContext, element: LookupElement): Boolean {
val insertedText = context.getDocument().getText(TextRange(context.getStartOffset(), context.getTailOffset()))
return insertedText == element.getUserData(KotlinCompletionCharFilter.SELECTED_ITEM_PREFIX)
}
public fun addElementWithAutoInsertionSuppressed(element: LookupElement) {
if (isResultEmpty && elements.isEmpty()) { /* without these checks we may get duplicated items */
addElement(element.suppressAutoInsertion())
@@ -39,6 +39,7 @@ import com.intellij.psi.PsiElement
import com.intellij.codeInsight.completion.InsertHandler
import org.jetbrains.jet.lang.resolve.name.Name
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
import org.jetbrains.jet.plugin.completion.handlers.WithTailInsertHandler
object NamedParametersCompletion {
private val positionFilter = AndFilter(
@@ -94,8 +95,6 @@ object NamedParametersCompletion {
.withIcon(JetIcons.PARAMETER)
.withInsertHandler(NamedParameterInsertHandler(name))
.assignPriority(ItemPriority.NAMED_PARAMETER)
lookupElement.putUserData(KotlinCompletionCharFilter.ACCEPT_EQ, true);
collector.addElement(lookupElement)
}
}
@@ -104,15 +103,15 @@ object NamedParametersCompletion {
private class NamedParameterInsertHandler(val parameterName: Name) : InsertHandler<LookupElement> {
override fun handleInsert(context: InsertionContext, item: LookupElement) {
val ch = context.getCompletionChar()
if (ch == '=' || ch == ' ') {
context.setAddCompletionChar(false)
}
val editor = context.getEditor()
val text = IdeDescriptorRenderers.SOURCE_CODE.renderName(parameterName) + " = "
val text = IdeDescriptorRenderers.SOURCE_CODE.renderName(parameterName)
editor.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), text)
editor.getCaretModel().moveToOffset(context.getStartOffset() + text.length)
if (context.getCompletionChar() == ' ') {
context.setAddCompletionChar(false)
}
WithTailInsertHandler.eqTail().postHandleInsert(context, item)
}
}
}
@@ -184,7 +184,7 @@ public class KotlinFunctionInsertHandler(val caretPosition : CaretPosition, val
}
private fun shouldPlaceCaretInBrackets(completionChar: Char): Boolean {
if (completionChar == ',' || completionChar == '.') return false
if (completionChar == ',' || completionChar == '.' || completionChar == '=') return false
if (completionChar == '(') return true
return caretPosition == CaretPosition.IN_BRACKETS
}
@@ -88,5 +88,6 @@ class WithTailInsertHandler(val tailText: String,
fun commaTail() = WithTailInsertHandler(",", spaceBefore = false, spaceAfter = true /*TODO: use code style option*/)
fun rparenthTail() = WithTailInsertHandler(")", spaceBefore = false, spaceAfter = false)
fun elseTail() = WithTailInsertHandler("else", spaceBefore = true, spaceAfter = true)
fun eqTail() = WithTailInsertHandler("=", spaceBefore = true, spaceAfter = true) /*TODO: use code style options*/
}
}
@@ -0,0 +1,8 @@
var vvv = 1
fun foo() {
<caret>
}
// ELEMENT: vvv
// CHAR: =
@@ -0,0 +1,8 @@
var vvv = 1
fun foo() {
vvv = <caret>
}
// ELEMENT: vvv
// CHAR: =
@@ -0,0 +1,10 @@
var vvv = 1
var vvv1 = 2
fun foo() {
vvv<caret>
}
// INVOCATION_COUNT: 0
// ELEMENT: *
// CHAR: =
@@ -0,0 +1,10 @@
var vvv = 1
var vvv1 = 2
fun foo() {
vvv=<caret>
}
// INVOCATION_COUNT: 0
// ELEMENT: *
// CHAR: =
@@ -19,7 +19,6 @@ package org.jetbrains.jet.completion.handlers;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.jet.JUnit3RunnerWithInners;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.InnerTestClasses;
import org.jetbrains.jet.test.TestMetadata;
import org.junit.runner.RunWith;
@@ -114,6 +113,18 @@ public class CompletionCharFilterTestGenerated extends AbstractCompletionCharFil
doTest(fileName);
}
@TestMetadata("Eq1.kt")
public void testEq1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Eq1.kt");
doTest(fileName);
}
@TestMetadata("Eq2.kt")
public void testEq2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Eq2.kt");
doTest(fileName);
}
@TestMetadata("FunctionWithLambdaArg1.kt")
public void testFunctionWithLambdaArg1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt");