diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index bec964b3f0e..26b10d50776 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -130,6 +130,7 @@ import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterMultiFileTest import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterForWebDemoTest import org.jetbrains.jet.plugin.decompiler.textBuilder.AbstractDecompiledTextTest import org.jetbrains.jet.completion.AbstractMultiFileSmartCompletionTest +import org.jetbrains.jet.completion.handlers.AbstractCompletionCharFilterTest fun main(args: Array) { System.setProperty("java.awt.headless", "true") @@ -358,6 +359,10 @@ fun main(args: Array) { model("completion/handlers/smart") } + testClass(javaClass()) { + model("completion/handlers/charFilter") + } + testClass(javaClass()) { model("completion/basic/codeFragments", extension = "kt") } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/KotlinCompletionCharFilter.kt b/idea/src/org/jetbrains/jet/plugin/completion/KotlinCompletionCharFilter.kt index 191b741e36d..f73ec225b90 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/KotlinCompletionCharFilter.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/KotlinCompletionCharFilter.kt @@ -25,17 +25,22 @@ import com.intellij.openapi.util.Key public class KotlinCompletionCharFilter() : CharFilter() { class object { - public val ACCEPT_OPENING_BRACE: Key = Key("KotlinCompletionCharFilter.ACCEPT_OPENNING_BRACE") - public val ACCEPT_EQ: Key = Key("KotlinCompletionCharFilter.ACCEPT_EQ") + public val ACCEPT_OPENING_BRACE: Key = Key("KotlinCompletionCharFilter.ACCEPT_OPENNING_BRACE") + public val ACCEPT_EQ: Key = Key("KotlinCompletionCharFilter.ACCEPT_EQ") } public override fun acceptChar(c : Char, prefixLength : Int, lookup : Lookup) : Result? { if (lookup.getPsiFile() !is JetFile) return null if (!lookup.isCompletion()) return null - if (Character.isJavaIdentifierPart(c) || c == ':' /* used in '::xxx'*/) return CharFilter.Result.ADD_TO_PREFIX + if (Character.isJavaIdentifierPart(c) || c == ':' /* used in '::xxx'*/) { + return CharFilter.Result.ADD_TO_PREFIX + } + + val currentItem = lookup.getCurrentItem() return when (c) { '.' -> { + //TODO: this heuristics better to be only used for auto-popup completion but I see no way to check this if (prefixLength == 0 && !lookup.isSelectionTouched()) { val caret = lookup.getEditor().getCaretModel().getOffset() if (caret > 0 && lookup.getEditor().getDocument().getCharsSequence()[caret - 1] == '.') { @@ -45,8 +50,7 @@ public class KotlinCompletionCharFilter() : CharFilter() { Result.SELECT_ITEM_AND_FINISH_LOOKUP } - '(' -> { - val currentItem = lookup.getCurrentItem() + '{' -> { if (currentItem != null && currentItem.getUserData(ACCEPT_OPENING_BRACE) ?: false) Result.SELECT_ITEM_AND_FINISH_LOOKUP else @@ -54,14 +58,13 @@ public class KotlinCompletionCharFilter() : CharFilter() { } '=' -> { - val currentItem = lookup.getCurrentItem() if (currentItem != null && currentItem.getUserData(ACCEPT_EQ) ?: false) Result.SELECT_ITEM_AND_FINISH_LOOKUP else - Result.HIDE_LOOKUP + Result.HIDE_LOOKUP //TODO: why not for others? } - ',', ' ' -> Result.SELECT_ITEM_AND_FINISH_LOOKUP + ',', ' ', '(' -> Result.SELECT_ITEM_AND_FINISH_LOOKUP else -> return CharFilter.Result.HIDE_LOOKUP } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/KotlinLookupElementFactory.kt b/idea/src/org/jetbrains/jet/plugin/completion/KotlinLookupElementFactory.kt index bb4235a3c12..635c331d472 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/KotlinLookupElementFactory.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/KotlinLookupElementFactory.kt @@ -88,14 +88,14 @@ public object KotlinLookupElementFactory { val insertHandler = getDefaultInsertHandler(descriptor) element = element.withInsertHandler(insertHandler) - if (insertHandler is JetFunctionInsertHandler && insertHandler.lambdaInfo != null) { - element.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true) - } - element = element.withTailText(tailText, true).withTypeText(typeText).withPresentableText(presentableText) element = element.withIcon(JetDescriptorIconProvider.getIcon(descriptor, declaration, Iconable.ICON_FLAG_VISIBILITY)) element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor)) + if (insertHandler is JetFunctionInsertHandler && insertHandler.lambdaInfo != null) { + element.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true) + } + return element } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/NamedParametersCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/NamedParametersCompletion.kt index c0f6c75939b..83fed85f1b7 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/NamedParametersCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/NamedParametersCompletion.kt @@ -88,8 +88,8 @@ object NamedParametersCompletion { val name = parameter.getName() val nameString = name.asString() if (nameString !in usedArguments) { - val text = "$nameString =" - val lookupElement = LookupElementBuilder.create(text) + val lookupElement = LookupElementBuilder.create(nameString) + .withPresentableText("$nameString =") .withTailText(" ${DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(parameter.getType())}") .withIcon(JetIcons.PARAMETER) .withInsertHandler(NamedParameterInsertHandler(name)) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/KotlinCallableInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/KotlinCallableInsertHandler.kt index c38552752cb..67a9b828616 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/KotlinCallableInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/KotlinCallableInsertHandler.kt @@ -126,13 +126,13 @@ public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val lam } private fun addBrackets(context : InsertionContext, offsetElement : PsiElement) { - if (context.getCompletionChar() == '(') { //TODO: more correct behavior related to braces type + val completionChar = context.getCompletionChar() + if (completionChar == '(') { //TODO: more correct behavior related to braces type context.setAddCompletionChar(false) } val offset = context.getTailOffset() val document = context.getDocument() - val completionChar = context.getCompletionChar() val forceParenthesis = lambdaInfo != null && completionChar == '\t' && document.getCharsSequence().charAt(offset) == '(' val braces = lambdaInfo != null && completionChar != '(' && !forceParenthesis @@ -168,7 +168,7 @@ public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val lam val closeBracketOffset = indexOfSkippingSpace(document, closingBracket, openingBracketOffset + 1) val editor = context.getEditor() - var forcePlaceCaretIntoParentheses : Boolean = completionChar == '(' + var forcePlaceCaretIntoParentheses = completionChar == '(' if (caretPosition == CaretPosition.IN_BRACKETS || forcePlaceCaretIntoParentheses || closeBracketOffset == -1) { editor.getCaretModel().moveToOffset(openingBracketOffset + 1 + inBracketsShift) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/WithTailInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/WithTailInsertHandler.kt index 1d4f1c3c3b2..854d7a5a8a2 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/WithTailInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/WithTailInsertHandler.kt @@ -30,9 +30,13 @@ class WithTailInsertHandler(val tailText: String, val spaceAfter: Boolean, val overwriteText: Boolean = true) : InsertHandler { override fun handleInsert(context: InsertionContext, item: LookupElement) { - val document = context.getDocument() - item.handleInsert(context) + + if (tailText == context.getCompletionChar().toString() && context.shouldAddCompletionChar()) { + return + } + + val document = context.getDocument() PsiDocumentManager.getInstance(context.getProject()).doPostponedOperationsAndUnblockDocument(document) var tailOffset = context.getTailOffset() diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/LambdaItems.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/LambdaItems.kt index 2651e00bc64..195b2fcb6a7 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/LambdaItems.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/LambdaItems.kt @@ -39,7 +39,6 @@ object LambdaItems { .suppressAutoInsertion() .assignSmartCompletionPriority(SmartCompletionItemPriority.LAMBDA_NO_PARAMS) .addTailAndNameSimilarity(functionExpectedInfos) - lookupElement.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true) collection.add(lookupElement) } @@ -56,7 +55,6 @@ object LambdaItems { .suppressAutoInsertion() .assignSmartCompletionPriority(SmartCompletionItemPriority.LAMBDA) .addTailAndNameSimilarity(functionExpectedInfos.filter { it.type == functionType }) - lookupElement.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true) collection.add(lookupElement) } } diff --git a/idea/testData/completion/basic/common/namedParameters/AfterBrace.kt b/idea/testData/completion/basic/common/namedParameters/AfterBrace.kt index ea13c7f99c2..e83610a629a 100644 --- a/idea/testData/completion/basic/common/namedParameters/AfterBrace.kt +++ b/idea/testData/completion/basic/common/namedParameters/AfterBrace.kt @@ -3,4 +3,4 @@ fun small(param: Int) { fun test() = small() -// EXIST: {"lookupString":"param =","tailText":" Int","itemText":"param ="} \ No newline at end of file +// EXIST: {"lookupString":"param","tailText":" Int","itemText":"param ="} \ No newline at end of file diff --git a/idea/testData/completion/basic/common/namedParameters/AfterComma.kt b/idea/testData/completion/basic/common/namedParameters/AfterComma.kt index c03edc69dac..ef6a1123010 100644 --- a/idea/testData/completion/basic/common/namedParameters/AfterComma.kt +++ b/idea/testData/completion/basic/common/namedParameters/AfterComma.kt @@ -3,5 +3,5 @@ fun small(first: Int, second: Int) { fun test() = small(12, ) -// ABSENT: "first =" -// EXIST: "second =" \ No newline at end of file +// ABSENT: first +// EXIST: { lookupString:"second", itemText:"second =" } diff --git a/idea/testData/completion/basic/common/namedParameters/CompactTypeNames.kt b/idea/testData/completion/basic/common/namedParameters/CompactTypeNames.kt index c9aab60647c..814668b7e5a 100644 --- a/idea/testData/completion/basic/common/namedParameters/CompactTypeNames.kt +++ b/idea/testData/completion/basic/common/namedParameters/CompactTypeNames.kt @@ -7,5 +7,5 @@ fun small(paramFirst: ArrayList, paramSecond: Comparable) -// EXIST: {"lookupString":"paramSecond =","tailText":" Comparable","itemText":"paramSecond ="} -// EXIST: {"lookupString":"paramFirst =","tailText":" ArrayList","itemText":"paramFirst ="} \ No newline at end of file +// EXIST: {"lookupString":"paramSecond","tailText":" Comparable","itemText":"paramSecond ="} +// EXIST: {"lookupString":"paramFirst","tailText":" ArrayList","itemText":"paramFirst ="} diff --git a/idea/testData/completion/basic/common/namedParameters/InParameterExpression.kt b/idea/testData/completion/basic/common/namedParameters/InParameterExpression.kt index 5fcb12a8ba8..a56aa5640ad 100644 --- a/idea/testData/completion/basic/common/namedParameters/InParameterExpression.kt +++ b/idea/testData/completion/basic/common/namedParameters/InParameterExpression.kt @@ -6,6 +6,6 @@ fun small(paramFirst: Int, paramSecond: Int) { fun test() = small(paramFirst = param) // EXIST: paramTest -// ABSENT: {"lookupString":"paramFirst =","tailText":" Int","itemText":"paramFirst ="} -// ABSENT: "paramSecond =" +// ABSENT: {"lookupString":"paramFirst","tailText":" Int","itemText":"paramFirst ="} +// ABSENT: paramSecond // NUMBER: 1 \ No newline at end of file diff --git a/idea/testData/completion/basic/common/namedParameters/NamedParametersFromOverloads.kt b/idea/testData/completion/basic/common/namedParameters/NamedParametersFromOverloads.kt index 3689fe27294..4deb4f76f59 100644 --- a/idea/testData/completion/basic/common/namedParameters/NamedParametersFromOverloads.kt +++ b/idea/testData/completion/basic/common/namedParameters/NamedParametersFromOverloads.kt @@ -10,11 +10,11 @@ fun other() { foo(n) } -// EXIST: "nFirst =" -// EXIST: "nSecond =" -// EXIST: "nThird =" +// EXIST: { lookupString:"nFirst", itemText:"nFirst =" } +// EXIST: { lookupString:"nSecond", itemText:"nSecond =" } +// EXIST: { lookupString:"nThird", itemText:"nThird =" } // EXIST: nLocal // todo - should exist -// ABSENT: "nClassParam =" -// ABSENT: "nClassField =" \ No newline at end of file +// ABSENT: nClassParam +// ABSENT: nClassField \ No newline at end of file diff --git a/idea/testData/completion/basic/common/namedParameters/NamedParamsInConstructor.kt b/idea/testData/completion/basic/common/namedParameters/NamedParamsInConstructor.kt index 1157af6638f..80932f3655c 100644 --- a/idea/testData/completion/basic/common/namedParameters/NamedParamsInConstructor.kt +++ b/idea/testData/completion/basic/common/namedParameters/NamedParamsInConstructor.kt @@ -6,5 +6,5 @@ fun other() { Foo(p) } -// EXIST: {"lookupString":"pFirst =","tailText":" String?","itemText":"pFirst ="} -// EXIST: {"lookupString":"pSecond =","tailText":" Int","itemText":"pSecond ="} \ No newline at end of file +// EXIST: {"lookupString":"pFirst","tailText":" String?","itemText":"pFirst ="} +// EXIST: {"lookupString":"pSecond","tailText":" Int","itemText":"pSecond ="} \ No newline at end of file diff --git a/idea/testData/completion/basic/common/namedParameters/NoAlreadyUsedParameters.kt b/idea/testData/completion/basic/common/namedParameters/NoAlreadyUsedParameters.kt index 91ab373cc44..d1fce8ccd54 100644 --- a/idea/testData/completion/basic/common/namedParameters/NoAlreadyUsedParameters.kt +++ b/idea/testData/completion/basic/common/namedParameters/NoAlreadyUsedParameters.kt @@ -4,8 +4,8 @@ fun test() { foo("str", paramThird = "test", param) } -// ABSENT: "paramFirst =" -// EXIST: "paramSecond =" -// ABSENT: "paramThird =" -// EXIST: "paramFourth =" +// ABSENT: paramFirst +// EXIST: paramSecond +// ABSENT: paramThird +// EXIST: paramFourth diff --git a/idea/testData/completion/basic/common/namedParameters/NoParamsFromUnapplicableOverload.kt b/idea/testData/completion/basic/common/namedParameters/NoParamsFromUnapplicableOverload.kt index d6cea25c235..5ea14fde416 100644 --- a/idea/testData/completion/basic/common/namedParameters/NoParamsFromUnapplicableOverload.kt +++ b/idea/testData/completion/basic/common/namedParameters/NoParamsFromUnapplicableOverload.kt @@ -5,7 +5,7 @@ fun test() { foo(12, param) } -// ABSENT: "paramFirst =" -// EXIST: {"lookupString":"paramSecond =","tailText":" Int","itemText":"paramSecond ="} -// ABSENT: "paramThird =" -// ABSENT: "paramFourth =" \ No newline at end of file +// ABSENT: paramFirst +// EXIST: {"lookupString":"paramSecond","tailText":" Int","itemText":"paramSecond ="} +// ABSENT: paramThird +// ABSENT: paramFourth \ No newline at end of file diff --git a/idea/testData/completion/basic/common/namedParameters/NotOnlyNamedParameters.kt b/idea/testData/completion/basic/common/namedParameters/NotOnlyNamedParameters.kt index 7d4c5506245..7fb4c496401 100644 --- a/idea/testData/completion/basic/common/namedParameters/NotOnlyNamedParameters.kt +++ b/idea/testData/completion/basic/common/namedParameters/NotOnlyNamedParameters.kt @@ -4,6 +4,6 @@ fun foo(first: Int, second: Int, third: String) { fun test(p: Int) = foo(12, , third = "") // EXIST: p -// ABSENT: "first =" -// EXIST: "third =" -// EXIST: "second =" +// ABSENT: first +// EXIST: third +// EXIST: second diff --git a/idea/testData/completion/basic/common/namedParameters/NotOnlyNamedParameters2.kt b/idea/testData/completion/basic/common/namedParameters/NotOnlyNamedParameters2.kt index 34e2cecdbf4..a5089cd1bad 100644 --- a/idea/testData/completion/basic/common/namedParameters/NotOnlyNamedParameters2.kt +++ b/idea/testData/completion/basic/common/namedParameters/NotOnlyNamedParameters2.kt @@ -4,6 +4,6 @@ fun foo(first: Int, second: Int, third: String) { fun test(p: Int) = foo(second = 3) // EXIST: p -// EXIST: "first =" -// EXIST: "second =" -// EXIST: "third =" +// EXIST: first +// EXIST: second +// EXIST: third diff --git a/idea/testData/completion/basic/common/namedParameters/OnlyNamedParameters.kt b/idea/testData/completion/basic/common/namedParameters/OnlyNamedParameters.kt index c3842ad223c..a0f5378bbf6 100644 --- a/idea/testData/completion/basic/common/namedParameters/OnlyNamedParameters.kt +++ b/idea/testData/completion/basic/common/namedParameters/OnlyNamedParameters.kt @@ -4,7 +4,7 @@ fun foo(first: Int, second: Int, third: String) { fun test(p: Int) = foo(12, third = "", ) // ABSENT: p -// ABSENT: "first =" -// ABSENT: "third =" -// EXIST: "second =" +// ABSENT: first +// ABSENT: third +// EXIST: second // NUMBER: 1 \ No newline at end of file diff --git a/idea/testData/completion/basic/common/namedParameters/WithParameterExpression.kt b/idea/testData/completion/basic/common/namedParameters/WithParameterExpression.kt index ce7fae1b6bd..dbe02b0f671 100644 --- a/idea/testData/completion/basic/common/namedParameters/WithParameterExpression.kt +++ b/idea/testData/completion/basic/common/namedParameters/WithParameterExpression.kt @@ -5,8 +5,8 @@ fun small(paramFirst: Int, paramSecond: Int) { fun test() = small(paramFirst = 12) -// EXIST: "paramFirst =" -// EXIST: "paramSecond =" +// EXIST: paramFirst +// EXIST: paramSecond // EXIST: paramTest // NUMBER: 3 \ No newline at end of file diff --git a/idea/testData/completion/basic/custom/NamedArgumentsKotlin.kt b/idea/testData/completion/basic/custom/NamedArgumentsKotlin.kt index 999df188137..7fc313d3a2b 100644 --- a/idea/testData/completion/basic/custom/NamedArgumentsKotlin.kt +++ b/idea/testData/completion/basic/custom/NamedArgumentsKotlin.kt @@ -2,5 +2,5 @@ import lib.KotlinClass fun test() = KotlinClass().foo() -// ABSENT: "p0 =" -// EXIST: "paramName =" +// ABSENT: p0 +// EXIST: { lookupString:"paramName", itemText:"paramName =" } diff --git a/idea/testData/completion/handlers/charFilter/Colon.kt b/idea/testData/completion/handlers/charFilter/Colon.kt new file mode 100644 index 00000000000..5161565a56a --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Colon.kt @@ -0,0 +1,11 @@ +fun foo(p: () -> Unit){} + +fun bar() { + foo() +} + +fun f(){} + +// COMPLETION_TYPE: SMART +// ELEMENT: * +// CHAR: : diff --git a/idea/testData/completion/handlers/charFilter/Colon.kt.after b/idea/testData/completion/handlers/charFilter/Colon.kt.after new file mode 100644 index 00000000000..7f4d2327482 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Colon.kt.after @@ -0,0 +1,11 @@ +fun foo(p: () -> Unit){} + +fun bar() { + foo(:) +} + +fun f(){} + +// COMPLETION_TYPE: SMART +// ELEMENT: * +// CHAR: : diff --git a/idea/testData/completion/handlers/charFilter/Comma1.kt b/idea/testData/completion/handlers/charFilter/Comma1.kt new file mode 100644 index 00000000000..780225cd90c --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Comma1.kt @@ -0,0 +1,9 @@ +fun foo(p1: Int) { } +fun foo(p1: Int, p2: Int) { } + +fun bar(ppp: Int, a: Int) { + foo() +} + +// ELEMENT: ppp +// CHAR: ',' diff --git a/idea/testData/completion/handlers/charFilter/Comma1.kt.after b/idea/testData/completion/handlers/charFilter/Comma1.kt.after new file mode 100644 index 00000000000..3936989074c --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Comma1.kt.after @@ -0,0 +1,9 @@ +fun foo(p1: Int) { } +fun foo(p1: Int, p2: Int) { } + +fun bar(ppp: Int, a: Int) { + foo(ppp,) +} + +// ELEMENT: ppp +// CHAR: ',' diff --git a/idea/testData/completion/handlers/charFilter/Comma2.kt b/idea/testData/completion/handlers/charFilter/Comma2.kt new file mode 100644 index 00000000000..e8759da4118 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Comma2.kt @@ -0,0 +1,9 @@ +fun foo(p1: Int, p2: Int) { } + +fun bar(pp: Int, a: Int) { + foo() +} + +// COMPLETION_TYPE: SMART +// ELEMENT: pp +// CHAR: ',' diff --git a/idea/testData/completion/handlers/charFilter/Comma2.kt.after b/idea/testData/completion/handlers/charFilter/Comma2.kt.after new file mode 100644 index 00000000000..227be05d111 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Comma2.kt.after @@ -0,0 +1,9 @@ +fun foo(p1: Int, p2: Int) { } + +fun bar(pp: Int, a: Int) { + foo(pp,) +} + +// COMPLETION_TYPE: SMART +// ELEMENT: pp +// CHAR: ',' diff --git a/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg1.kt b/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg1.kt new file mode 100644 index 00000000000..1611201e415 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg1.kt @@ -0,0 +1,9 @@ +class C(filter: (String) -> Boolean) + +fun foo(p: C) { + val c: C = +} + +// COMPLETION_TYPE: SMART +// ELEMENT: C +// CHAR: { diff --git a/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg1.kt.after b/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg1.kt.after new file mode 100644 index 00000000000..bc40e5cc0de --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg1.kt.after @@ -0,0 +1,9 @@ +class C(filter: (String) -> Boolean) + +fun foo(p: C) { + val c: C = C { } +} + +// COMPLETION_TYPE: SMART +// ELEMENT: C +// CHAR: { diff --git a/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg2.kt b/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg2.kt new file mode 100644 index 00000000000..3d448ebae8c --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg2.kt @@ -0,0 +1,9 @@ +class C(filter: (String) -> Boolean) + +fun foo(p: C) { + val c: C = +} + +// COMPLETION_TYPE: SMART +// ELEMENT: C +// CHAR: ( diff --git a/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg2.kt.after b/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg2.kt.after new file mode 100644 index 00000000000..f73867b565a --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg2.kt.after @@ -0,0 +1,9 @@ +class C(filter: (String) -> Boolean) + +fun foo(p: C) { + val c: C = C() +} + +// COMPLETION_TYPE: SMART +// ELEMENT: C +// CHAR: ( diff --git a/idea/testData/completion/handlers/charFilter/Dot.kt b/idea/testData/completion/handlers/charFilter/Dot.kt new file mode 100644 index 00000000000..c0b0cf47e77 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Dot.kt @@ -0,0 +1,7 @@ +fun foo(o: Any) { + o. +} + +// INVOCATION_COUNT: 0 +// ELEMENT: hashCode +// CHAR: . \ No newline at end of file diff --git a/idea/testData/completion/handlers/charFilter/Dot.kt.after b/idea/testData/completion/handlers/charFilter/Dot.kt.after new file mode 100644 index 00000000000..45c4f5f596e --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Dot.kt.after @@ -0,0 +1,7 @@ +fun foo(o: Any) { + o.hashCode(). +} + +// INVOCATION_COUNT: 0 +// ELEMENT: hashCode +// CHAR: . \ No newline at end of file diff --git a/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt b/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt new file mode 100644 index 00000000000..61878c7b387 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt @@ -0,0 +1,8 @@ +fun foo(filter: (String) -> Boolean) {} + +fun bar() { + f +} + +// ELEMENT: foo +// CHAR: { diff --git a/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt.after b/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt.after new file mode 100644 index 00000000000..890f184b065 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt.after @@ -0,0 +1,8 @@ +fun foo(filter: (String) -> Boolean) {} + +fun bar() { + foo { } +} + +// ELEMENT: foo +// CHAR: { diff --git a/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg2.kt b/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg2.kt new file mode 100644 index 00000000000..ac221b703bb --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg2.kt @@ -0,0 +1,8 @@ +fun foo(filter: (String) -> Boolean) {} + +fun bar() { + f +} + +// ELEMENT: foo +// CHAR: ( diff --git a/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg2.kt.after b/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg2.kt.after new file mode 100644 index 00000000000..1229b28f7fe --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg2.kt.after @@ -0,0 +1,8 @@ +fun foo(filter: (String) -> Boolean) {} + +fun bar() { + foo() +} + +// ELEMENT: foo +// CHAR: ( diff --git a/idea/testData/completion/handlers/charFilter/LParenth.kt b/idea/testData/completion/handlers/charFilter/LParenth.kt new file mode 100644 index 00000000000..d43c44c3004 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/LParenth.kt @@ -0,0 +1,8 @@ +fun foo() { } + +fun bar() { + f +} + +// ELEMENT: foo +// CHAR: ( diff --git a/idea/testData/completion/handlers/charFilter/LParenth.kt.after b/idea/testData/completion/handlers/charFilter/LParenth.kt.after new file mode 100644 index 00000000000..0991572924d --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/LParenth.kt.after @@ -0,0 +1,8 @@ +fun foo() { } + +fun bar() { + foo() +} + +// ELEMENT: foo +// CHAR: ( diff --git a/idea/testData/completion/handlers/charFilter/NamedParameter1.kt b/idea/testData/completion/handlers/charFilter/NamedParameter1.kt new file mode 100644 index 00000000000..4c4b4ddb05c --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/NamedParameter1.kt @@ -0,0 +1,8 @@ +fun foo(xxx: Int, yyy: Int) + +fun test() { + foo(xxx = 10, ) +} + +// ELEMENT: yyy +// CHAR: = diff --git a/idea/testData/completion/handlers/charFilter/NamedParameter1.kt.after b/idea/testData/completion/handlers/charFilter/NamedParameter1.kt.after new file mode 100644 index 00000000000..57d46120ddb --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/NamedParameter1.kt.after @@ -0,0 +1,8 @@ +fun foo(xxx: Int, yyy: Int) + +fun test() { + foo(xxx = 10, yyy = ) +} + +// ELEMENT: yyy +// CHAR: = diff --git a/idea/testData/completion/handlers/charFilter/NamedParameter2.kt b/idea/testData/completion/handlers/charFilter/NamedParameter2.kt new file mode 100644 index 00000000000..d73bf3fbca6 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/NamedParameter2.kt @@ -0,0 +1,8 @@ +fun foo(xxx: Int, yyy: Int) + +fun test() { + foo(xxx = 10, ) +} + +// ELEMENT: yyy +// CHAR: ' ' diff --git a/idea/testData/completion/handlers/charFilter/NamedParameter2.kt.after b/idea/testData/completion/handlers/charFilter/NamedParameter2.kt.after new file mode 100644 index 00000000000..56fd63c7079 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/NamedParameter2.kt.after @@ -0,0 +1,8 @@ +fun foo(xxx: Int, yyy: Int) + +fun test() { + foo(xxx = 10, yyy = ) +} + +// ELEMENT: yyy +// CHAR: ' ' diff --git a/idea/testData/completion/handlers/charFilter/RangeTyping.kt b/idea/testData/completion/handlers/charFilter/RangeTyping.kt new file mode 100644 index 00000000000..de566265194 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/RangeTyping.kt @@ -0,0 +1,7 @@ +fun foo(start: Int) { + val range = start. +} + +// INVOCATION_COUNT: 0 +// ELEMENT: * +// CHAR: . \ No newline at end of file diff --git a/idea/testData/completion/handlers/charFilter/RangeTyping.kt.after b/idea/testData/completion/handlers/charFilter/RangeTyping.kt.after new file mode 100644 index 00000000000..1b0b4818433 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/RangeTyping.kt.after @@ -0,0 +1,7 @@ +fun foo(start: Int) { + val range = start.. +} + +// INVOCATION_COUNT: 0 +// ELEMENT: * +// CHAR: . \ No newline at end of file diff --git a/idea/testData/completion/handlers/charFilter/Space.kt b/idea/testData/completion/handlers/charFilter/Space.kt new file mode 100644 index 00000000000..3d909bfc19b --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Space.kt @@ -0,0 +1,4 @@ +class A : A + +// ELEMENT: Annotation +// CHAR: ' ' diff --git a/idea/testData/completion/handlers/charFilter/Space.kt.after b/idea/testData/completion/handlers/charFilter/Space.kt.after new file mode 100644 index 00000000000..7241aff50f3 --- /dev/null +++ b/idea/testData/completion/handlers/charFilter/Space.kt.after @@ -0,0 +1,4 @@ +class A : Annotation + +// ELEMENT: Annotation +// CHAR: ' ' diff --git a/idea/testData/completion/weighers/basic/NamedParameters.kt b/idea/testData/completion/weighers/basic/NamedParameters.kt index 2fc62d82a86..4d6654a16bb 100644 --- a/idea/testData/completion/weighers/basic/NamedParameters.kt +++ b/idea/testData/completion/weighers/basic/NamedParameters.kt @@ -18,5 +18,5 @@ fun test(listParam: Int) { // ORDER: listImportedVal // ORDER: listThisFileFun // ORDER: listImportedFun -// ORDER: "listMatch =" -// ORDER: "listNew =" +// ORDER: listMatch +// ORDER: listNew diff --git a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java index 61213683df2..d33cd3e378f 100644 --- a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.completion; 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; diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/AbstractSmartCompletionHandlerTest.kt b/idea/tests/org/jetbrains/jet/completion/handlers/AbstractSmartCompletionHandlerTest.kt index 6eab9f82817..c70a815f0fd 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/AbstractSmartCompletionHandlerTest.kt +++ b/idea/tests/org/jetbrains/jet/completion/handlers/AbstractSmartCompletionHandlerTest.kt @@ -16,33 +16,16 @@ package org.jetbrains.jet.completion.handlers -import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase import com.intellij.codeInsight.completion.CompletionType -import com.intellij.psi.codeStyle.CodeStyleSettingsManager -import org.jetbrains.jet.plugin.formatter.JetCodeStyleSettings -import com.intellij.codeInsight.lookup.LookupElement -import java.io.File -import org.jetbrains.jet.plugin.PluginTestCaseBase -import com.intellij.codeInsight.lookup.impl.LookupImpl -import com.intellij.codeInsight.lookup.LookupEvent -import com.intellij.openapi.command.WriteCommandAction -import com.intellij.codeInsight.lookup.LookupManager -import com.intellij.codeInsight.lookup.LookupElementPresentation -import org.junit.Assert -import com.intellij.openapi.application.Result -import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture -import kotlin.properties.Delegates import org.jetbrains.jet.InTextDirectivesUtils -public abstract class AbstractSmartCompletionHandlerTest() : CompletionHandlerTestBase() { +public abstract class AbstractCompletionHandlerTest() : CompletionHandlerTestBase() { private val INVOCATION_COUNT_PREFIX = "INVOCATION_COUNT:" private val LOOKUP_STRING_PREFIX = "ELEMENT:" private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:" private val TAIL_TEXT_PREFIX = "TAIL_TEXT:" private val COMPLETION_CHAR_PREFIX = "CHAR:" - - override val completionType: CompletionType = CompletionType.SMART - override val testDataRelativePath: String = "/completion/handlers/smart" + private val COMPLETION_TYPE_PREFIX = "COMPLETION_TYPE:" protected fun doTest(testPath: String) { fixture.configureByFile(testPath) @@ -52,12 +35,34 @@ public abstract class AbstractSmartCompletionHandlerTest() : CompletionHandlerTe val lookupString = InTextDirectivesUtils.findStringWithPrefixes(fileText, LOOKUP_STRING_PREFIX) val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX) val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX) + val completionCharString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX) val completionChar = when(completionCharString) { "\\n", null -> '\n' "\\t" -> '\t' - else -> error("Uknown completion char") + else -> completionCharString.singleOrNull() ?: error("Incorrect completion char: \"$completionCharString\"") } - doTestWithTextLoaded(invocationCount, lookupString, itemText, tailText, completionChar) + + val completionTypeString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_TYPE_PREFIX) + val completionType = when (completionTypeString) { + "BASIC" -> CompletionType.BASIC + "SMART" -> CompletionType.SMART + null -> defaultCompletionType + else -> error("Unknown completion type: $completionTypeString") + } + + doTestWithTextLoaded(completionType, invocationCount, lookupString, itemText, tailText, completionChar) } + + protected abstract val defaultCompletionType: CompletionType +} + +public abstract class AbstractSmartCompletionHandlerTest() : AbstractCompletionHandlerTest() { + override val defaultCompletionType: CompletionType = CompletionType.SMART + override val testDataRelativePath: String = "/completion/handlers/smart" +} + +public abstract class AbstractCompletionCharFilterTest() : AbstractCompletionHandlerTest() { + override val defaultCompletionType: CompletionType = CompletionType.BASIC + override val testDataRelativePath: String = "/completion/handlers/charFilter" } diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt b/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt index e88e8dabf04..f503ccb5776 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt +++ b/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt @@ -21,9 +21,21 @@ import org.jetbrains.jet.plugin.formatter.JetCodeStyleSettings import com.intellij.psi.codeStyle.CodeStyleSettingsManager public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){ - override val completionType: CompletionType = CompletionType.BASIC override val testDataRelativePath: String = "/completion/handlers" + private fun doTest() { + doTest(2, "*", null, null, '\n') + } + + private fun doTest(time: Int, lookupString: String?, tailText: String?, completionChar: Char) { + doTest(time, lookupString, null, tailText, completionChar) + } + + private fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) { + fixture.configureByFile(fileName()) + doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar) + } + fun testClassCompletionImport() = doTest(2, "SortedSet", null, '\n') fun testClassCompletionInMiddle() = doTest(1, "TimeZone", " (java.util)", '\t') @@ -48,9 +60,9 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){ fun testNamedParametersCompletion() = doTest() - fun testNamedParametersCompletionOnEqual() = doTest(0, "paramTest =", null, '=') + fun testNamedParametersCompletionOnEqual() = doTest(0, "paramTest", "paramTest =", null, '=') - fun testNamedParameterKeywordName() = doTest(1, "class =", null, '\n') + fun testNamedParameterKeywordName() = doTest(1, "class", "class =", null, '\n') fun testInsertJavaClassImport() = doTest() diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionCharFilterTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionCharFilterTestGenerated.java new file mode 100644 index 00000000000..da658eaffc4 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionCharFilterTestGenerated.java @@ -0,0 +1,116 @@ +/* + * Copyright 2010-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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/completion/handlers/charFilter") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class CompletionCharFilterTestGenerated extends AbstractCompletionCharFilterTest { + public void testAllFilesPresentInCharFilter() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/completion/handlers/charFilter"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Colon.kt") + public void testColon() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Colon.kt"); + doTest(fileName); + } + + @TestMetadata("Comma1.kt") + public void testComma1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Comma1.kt"); + doTest(fileName); + } + + @TestMetadata("Comma2.kt") + public void testComma2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Comma2.kt"); + doTest(fileName); + } + + @TestMetadata("ConstructorWithLambdaArg1.kt") + public void testConstructorWithLambdaArg1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg1.kt"); + doTest(fileName); + } + + @TestMetadata("ConstructorWithLambdaArg2.kt") + public void testConstructorWithLambdaArg2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg2.kt"); + doTest(fileName); + } + + @TestMetadata("Dot.kt") + public void testDot() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Dot.kt"); + doTest(fileName); + } + + @TestMetadata("FunctionWithLambdaArg1.kt") + public void testFunctionWithLambdaArg1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt"); + doTest(fileName); + } + + @TestMetadata("FunctionWithLambdaArg2.kt") + public void testFunctionWithLambdaArg2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg2.kt"); + doTest(fileName); + } + + @TestMetadata("LParenth.kt") + public void testLParenth() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/LParenth.kt"); + doTest(fileName); + } + + @TestMetadata("NamedParameter1.kt") + public void testNamedParameter1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/NamedParameter1.kt"); + doTest(fileName); + } + + @TestMetadata("NamedParameter2.kt") + public void testNamedParameter2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/NamedParameter2.kt"); + doTest(fileName); + } + + @TestMetadata("RangeTyping.kt") + public void testRangeTyping() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/RangeTyping.kt"); + doTest(fileName); + } + + @TestMetadata("Space.kt") + public void testSpace() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Space.kt"); + doTest(fileName); + } +} diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt index d00a2fdf8fc..366c95f966a 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt @@ -31,24 +31,19 @@ import com.intellij.openapi.application.Result import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTestCase() { - protected abstract val completionType : CompletionType protected abstract val testDataRelativePath: String protected val fixture: JavaCodeInsightTestFixture get() = myFixture - protected fun doTest() : Unit = doTest(2, "*", null, null, '\n') - - protected fun doTest(time: Int, lookupString: String?, tailText: String?, completionChar: Char) { - doTest(time, lookupString, null, tailText, completionChar) - } - - protected fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) { - fixture.configureByFile(fileName()) - doTestWithTextLoaded(time, lookupString, itemText, tailText, completionChar) - } - - protected fun doTestWithTextLoaded(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) { + protected fun doTestWithTextLoaded( + completionType: CompletionType, + time: Int, + lookupString: String?, + itemText: String?, + tailText: String?, + completionChar: Char + ) { fixture.complete(completionType, time) if (lookupString != null || itemText != null || tailText != null) { @@ -126,7 +121,9 @@ public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTe protected fun selectItem(item: LookupElement?, completionChar: Char) { val lookup = (fixture.getLookup() as LookupImpl) - lookup.setCurrentItem(item) + if (lookup.getCurrentItem() != item) { // do not touch selection if not changed - important for char filter tests + lookup.setCurrentItem(item) + } if (LookupEvent.isSpecialCompletionChar(completionChar)) { (object : WriteCommandAction.Simple(getProject()) { protected override fun run(result: Result) {