From 6284f557e67a5e7389ed7312e45b0eccbeb1c603 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 18 May 2015 11:08:07 +0300 Subject: [PATCH] Smart completion: sometimes we can insert comma after vararg argument too --- .../kotlin/idea/completion/ExpectedInfos.kt | 48 +++++++++---------- .../handlers/smart/SecondVararg.kt.after | 2 +- .../smart/VarargWithParameterAfter.kt | 7 +++ .../smart/VarargWithParameterAfter.kt.after | 7 +++ .../SmartCompletionHandlerTestGenerated.java | 6 +++ 5 files changed, 45 insertions(+), 25 deletions(-) create mode 100644 idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt create mode 100644 idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt.after diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ExpectedInfos.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ExpectedInfos.kt index f2b6c9329ee..93b5ba48f8d 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ExpectedInfos.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ExpectedInfos.kt @@ -183,35 +183,46 @@ class ExpectedInfos( val expectedName = if (descriptor.hasSynthesizedParameterNames()) null else parameter.getName().asString() + val lastNonOptionalParam = parameters.lastOrNull { !it.hasDefaultValue() } + + fun needCommaForParameter(parameter: ValueParameterDescriptor): Boolean { + if (parameter.hasDefaultValue()) return false // parameter is optional + if (parameter.getVarargElementType() != null) return false // vararg arguments list can be empty + // last non-optional parameter of functional type can be placed outside parenthesis: + if (parameter == lastNonOptionalParam && KotlinBuiltIns.isFunctionOrExtensionFunctionType(parameter.getType())) return false + return true + } + + val tail = if (argumentName == null) { + if (parameter == parameters.last()) + Tail.RPARENTH //TODO: support square brackets + else if (parameters.dropWhile { it != parameter }.drop(1).any(::needCommaForParameter)) + Tail.COMMA + else + null + } + else { + namedArgumentTail(argumentToParameter, argumentName, descriptor) + } + val varargElementType = parameter.getVarargElementType() if (varargElementType != null) { if (isFunctionLiteralArgument) continue if (argumentName == null) { - expectedInfos.add(ArgumentExpectedInfo(varargElementType, expectedName?.unpluralize(), null, descriptor, argumentPosition)) + expectedInfos.add(ArgumentExpectedInfo(varargElementType, expectedName?.unpluralize(), + if (tail == Tail.RPARENTH) null else tail, descriptor, argumentPosition)) if (argumentIndex == parameters.indexOf(parameter)) { - val tail = if (parameter == parameters.last()) Tail.RPARENTH else null expectedInfos.add(ArgumentExpectedInfo(parameter.getType(), expectedName, tail, descriptor, argumentPosition, ItemOptions.STAR_PREFIX)) } } else { - val tail = namedArgumentTail(argumentToParameter, argumentName, descriptor) expectedInfos.add(ArgumentExpectedInfo(varargElementType, expectedName?.unpluralize(), tail, descriptor, argumentPosition)) expectedInfos.add(ArgumentExpectedInfo(parameter.getType(), expectedName, tail, descriptor, argumentPosition, ItemOptions.STAR_PREFIX)) } } else { - val lastNonOptionalParam = parameters.lastOrNull { !it.hasDefaultValue() } - - fun needCommaForParameter(parameter: ValueParameterDescriptor): Boolean { - if (parameter.hasDefaultValue()) return false // parameter is optional - if (parameter.getVarargElementType() != null) return false // vararg arguments list can be empty - // last non-optional parameter of functional type can be placed outside parenthesis: - if (parameter == lastNonOptionalParam && KotlinBuiltIns.isFunctionOrExtensionFunctionType(parameter.getType())) return false - return true - } - val parameterType = if (useHeuristicSignatures) HeuristicSignatures.correctedParameterType(descriptor, parameter, moduleDescriptor, callElement.getProject()) ?: parameter.getType() else @@ -223,17 +234,6 @@ class ExpectedInfos( } } else { - val tail = if (argumentName == null) { - if (parameter == parameters.last()) - Tail.RPARENTH //TODO: support square brackets - else if (parameters.dropWhile { it != parameter }.drop(1).none(::needCommaForParameter)) - null - else - Tail.COMMA - } - else { - namedArgumentTail(argumentToParameter, argumentName, descriptor) - } expectedInfos.add(ArgumentExpectedInfo(parameterType, expectedName, tail, descriptor, argumentPosition)) } diff --git a/idea/idea-completion/testData/handlers/smart/SecondVararg.kt.after b/idea/idea-completion/testData/handlers/smart/SecondVararg.kt.after index e9e9feb8f77..3692e050b74 100644 --- a/idea/idea-completion/testData/handlers/smart/SecondVararg.kt.after +++ b/idea/idea-completion/testData/handlers/smart/SecondVararg.kt.after @@ -1,7 +1,7 @@ fun foo(vararg v1: Int, vararg v2: Char, s: String) { } fun bar(c: Char) { - foo(*intArrayOf(), c) + foo(*intArrayOf(), c, ) } // ELEMENT: c diff --git a/idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt b/idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt new file mode 100644 index 00000000000..5c535300b55 --- /dev/null +++ b/idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt @@ -0,0 +1,7 @@ +fun foo(vararg strings: String, p: String){ } + +fun bar(s: String){ + foo() +} + +// ELEMENT: s diff --git a/idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt.after b/idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt.after new file mode 100644 index 00000000000..e0449cb6342 --- /dev/null +++ b/idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt.after @@ -0,0 +1,7 @@ +fun foo(vararg strings: String, p: String){ } + +fun bar(s: String){ + foo(s, ) +} + +// ELEMENT: s diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java index 775f0b969b9..f5c8da25a89 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java @@ -761,6 +761,12 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion doTest(fileName); } + @TestMetadata("VarargWithParameterAfter.kt") + public void testVarargWithParameterAfter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/VarargWithParameterAfter.kt"); + doTest(fileName); + } + @TestMetadata("WhenElse.kt") public void testWhenElse() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/WhenElse.kt");