From a9362d844ae6f63b8272c14caaf68f810d7391f3 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Thu, 20 Dec 2018 14:38:35 +0300 Subject: [PATCH] Implemented "Complete statement" for completion #KT-18663 fixed --- .../handlers/KotlinFunctionInsertHandler.kt | 19 ++- .../test/SmartEnterCompletionTest.kt | 132 ++++++++++++++++++ 2 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/SmartEnterCompletionTest.kt diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt index cfe4a0dfae9..8858d1a743c 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt @@ -93,15 +93,18 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable val project = context.project val chars = document.charsSequence - val insertLambda = lambdaInfo != null && completionChar != '(' && !(completionChar == '\t' && chars.isCharAt(offset, '(')) + val isSmartEnterCompletion = completionChar == Lookup.COMPLETE_STATEMENT_SELECT_CHAR + val isReplaceCompletion = completionChar == Lookup.REPLACE_SELECT_CHAR + val isNormalCompletion = completionChar == Lookup.NORMAL_SELECT_CHAR + + val insertLambda = lambdaInfo != null && completionChar != '(' && !(isReplaceCompletion && chars.isCharAt(offset, '(')) val openingBracket = if (insertLambda) '{' else '(' val closingBracket = if (insertLambda) '}' else ')' - var insertTypeArguments = - inputTypeArguments && (completionChar == '\n' || completionChar == '\r' || completionChar == Lookup.REPLACE_SELECT_CHAR) + var insertTypeArguments = inputTypeArguments && (isNormalCompletion || isReplaceCompletion || isSmartEnterCompletion) - if (completionChar == Lookup.REPLACE_SELECT_CHAR) { + if (isReplaceCompletion) { val offset1 = chars.skipSpaces(offset) if (offset1 < chars.length) { if (chars[offset1] == '<') { @@ -149,12 +152,16 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable document.insertString(offset, " {}") } } else { - document.insertString(offset, "()") + if (isSmartEnterCompletion) { + document.insertString(offset, "(") + } else { + document.insertString(offset, "()") + } } PsiDocumentManager.getInstance(project).commitDocument(document) openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset)!! - closeBracketOffset = chars.indexOfSkippingSpace(closingBracket, openingBracketOffset + 1)!! + closeBracketOffset = chars.indexOfSkippingSpace(closingBracket, openingBracketOffset + 1) } if (insertLambda && lambdaInfo!!.explicitParameters) { diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/SmartEnterCompletionTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/SmartEnterCompletionTest.kt new file mode 100644 index 00000000000..b98c5fc6525 --- /dev/null +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/SmartEnterCompletionTest.kt @@ -0,0 +1,132 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.completion.test + +import com.intellij.codeInsight.lookup.Lookup +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase + +class SmartEnterCompletionTest : KotlinLightCodeInsightFixtureTestCase() { + + fun testBasic() { + doTest( + """ + fun foo(p:String) {} + + fun test() { + val s = "" + fos + } + """, """ + fun foo(p:String) {} + + fun test() { + val s = "" + foo(s) + } + """ + ) + } + + fun testEncloseCall() { + doTest( + """ + fun foo(p:String) {} + fun bar(p:String): String = p + + fun test() { + val s = "" + fobar(s) + } + """, """ + fun foo(p:String) {} + fun bar(p:String): String = p + + fun test() { + val s = "" + foo(bar(s)) + } + """ + ) + } + + fun testFinishOuterCall() { + doTest( + """ + fun foo(p:String) {} + fun bar(p:String): String = p + + fun test() { + val s = "" + foo(bas) + } + """, """ + fun foo(p:String) {} + fun bar(p:String): String = p + + fun test() { + val s = "" + foo(bar(s)) + } + """ + ) + } + + fun testIf() { + doTest( + """ + fun foo(p:String): Boolean = false + + fun test() { + val s = "" + if (fos + } + """, """ + fun foo(p:String): Boolean = false + + fun test() { + val s = "" + if (foo(s)) { + + } + } + """ + ) + } + + fun testTwoLineBinaryExpr() { + doTest( + """ + fun foo(p:Int) {} + + fun test() { + fo1 + + 2 + } + """, """ + fun foo(p:Int) {} + + fun test() { + foo(1 + + 2) + } + """ + ) + } + + fun doTest(before: String, after: String) { + with(myFixture) { + configureByText(KotlinFileType.INSTANCE, before) + completeBasic() + type(Lookup.COMPLETE_STATEMENT_SELECT_CHAR) + checkResult(after) + } + } + + override fun getProjectDescriptor(): LightProjectDescriptor = LightCodeInsightFixtureTestCase.JAVA_LATEST +} \ No newline at end of file