From 2de52290982b9a7efe6cf1158e153daa62054de2 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 27 Aug 2015 22:38:03 +0300 Subject: [PATCH] Additional item inserting lambda provided by completion when all parameters before the last are optional --- .../kotlin/renderer/DescriptorRenderer.kt | 22 ++++---- .../kotlin/renderer/DescriptorRendererImpl.kt | 29 +++++----- .../HtmlTabledDescriptorRenderer.java | 19 ++++--- .../completion/BasicLookupElementFactory.kt | 12 ++-- .../idea/completion/LookupElementFactory.kt | 55 ++++++++++++------- .../completion/handlers/GenerateLambda.kt | 3 +- .../idea/completion/smart/LambdaItems.kt | 8 +-- .../highOrderFunctions/OptionalParameters.kt | 25 +++++++++ .../highOrderFunctions/OptionalParameters1.kt | 9 +++ .../OptionalParameters1.kt.after | 9 +++ .../highOrderFunctions/OptionalParameters2.kt | 9 +++ .../OptionalParameters2.kt.after | 9 +++ .../test/JSBasicCompletionTestGenerated.java | 6 ++ .../test/JvmBasicCompletionTestGenerated.java | 6 ++ .../BasicCompletionHandlerTestGenerated.java | 12 ++++ 15 files changed, 169 insertions(+), 64 deletions(-) create mode 100644 idea/idea-completion/testData/basic/common/highOrderFunctions/OptionalParameters.kt create mode 100644 idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt create mode 100644 idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt.after create mode 100644 idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt create mode 100644 idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt.after diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt index f7c2a847ed7..3c90a98a6a9 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt @@ -47,34 +47,36 @@ public interface DescriptorRenderer : Renderer { override fun render(declarationDescriptor: DeclarationDescriptor): String + public fun renderValueParameters(parameters: Collection, synthesizedParameterNames: Boolean): String + public fun renderFunctionParameters(functionDescriptor: FunctionDescriptor): String + = renderValueParameters(functionDescriptor.valueParameters, functionDescriptor.hasSynthesizedParameterNames()) public fun renderName(name: Name): String public fun renderFqName(fqName: FqNameBase): String public interface ValueParametersHandler { - public fun appendBeforeValueParameters(function: FunctionDescriptor, builder: StringBuilder) - public fun appendAfterValueParameters(function: FunctionDescriptor, builder: StringBuilder) + public fun appendBeforeValueParameters(parameterCount: Int, builder: StringBuilder) + public fun appendAfterValueParameters(parameterCount: Int, builder: StringBuilder) - public fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, builder: StringBuilder) - public fun appendAfterValueParameter(parameter: ValueParameterDescriptor, builder: StringBuilder) + public fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, parameterIndex: Int, parameterCount: Int, builder: StringBuilder) + public fun appendAfterValueParameter(parameter: ValueParameterDescriptor, parameterIndex: Int, parameterCount: Int, builder: StringBuilder) public object DEFAULT : ValueParametersHandler { - override fun appendBeforeValueParameters(function: FunctionDescriptor, builder: StringBuilder) { + override fun appendBeforeValueParameters(parameterCount: Int, builder: StringBuilder) { builder.append("(") } - override fun appendAfterValueParameters(function: FunctionDescriptor, builder: StringBuilder) { + override fun appendAfterValueParameters(parameterCount: Int, builder: StringBuilder) { builder.append(")") } - override fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, builder: StringBuilder) { + override fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, parameterIndex: Int, parameterCount: Int, builder: StringBuilder) { } - override fun appendAfterValueParameter(parameter: ValueParameterDescriptor, builder: StringBuilder) { - val function = parameter.getContainingDeclaration() as FunctionDescriptor - if (parameter.getIndex() != function.getValueParameters().size() - 1) { + override fun appendAfterValueParameter(parameter: ValueParameterDescriptor, parameterIndex: Int, parameterCount: Int, builder: StringBuilder) { + if (parameterIndex != parameterCount - 1) { builder.append(", ") } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt index d8d777a1970..98696f27b6e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt @@ -548,7 +548,7 @@ internal class DescriptorRendererImpl( renderName(function, builder) - renderValueParameters(function, builder) + renderValueParameters(function.valueParameters, function.hasSynthesizedParameterNames(), builder) renderReceiverAfterName(function, builder) @@ -594,7 +594,7 @@ internal class DescriptorRendererImpl( renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder, false) } - renderValueParameters(constructor, builder) + renderValueParameters(constructor.valueParameters, constructor.hasSynthesizedParameterNames(), builder) if (secondaryConstructorsAsPrimary) { renderWhereSuffix(constructor.getTypeParameters(), builder) @@ -618,25 +618,26 @@ internal class DescriptorRendererImpl( } } - override fun renderFunctionParameters(functionDescriptor: FunctionDescriptor): String { - return StringBuilder { renderValueParameters(functionDescriptor, this) }.toString() + override fun renderValueParameters(parameters: Collection, synthesizedParameterNames: Boolean): String { + return StringBuilder { renderValueParameters(parameters, synthesizedParameterNames, this) }.toString() } - private fun renderValueParameters(function: FunctionDescriptor, builder: StringBuilder) { - val includeNames = shouldRenderParameterNames(function) - valueParametersHandler.appendBeforeValueParameters(function, builder) - for (parameter in function.getValueParameters()) { - valueParametersHandler.appendBeforeValueParameter(parameter, builder) + private fun renderValueParameters(parameters: Collection, synthesizedParameterNames: Boolean, builder: StringBuilder) { + val includeNames = shouldRenderParameterNames(synthesizedParameterNames) + val parameterCount = parameters.size() + valueParametersHandler.appendBeforeValueParameters(parameterCount, builder) + for ((index, parameter) in parameters.withIndex()) { + valueParametersHandler.appendBeforeValueParameter(parameter, index, parameterCount, builder) renderValueParameter(parameter, includeNames, builder, false) - valueParametersHandler.appendAfterValueParameter(parameter, builder) + valueParametersHandler.appendAfterValueParameter(parameter, index, parameterCount, builder) } - valueParametersHandler.appendAfterValueParameters(function, builder) + valueParametersHandler.appendAfterValueParameters(parameterCount, builder) } - private fun shouldRenderParameterNames(function: FunctionDescriptor): Boolean { + private fun shouldRenderParameterNames(synthesizedParameterNames: Boolean): Boolean { when (parameterNameRenderingPolicy) { ParameterNameRenderingPolicy.ALL -> return true - ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED -> return !function.hasSynthesizedParameterNames() + ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED -> return !synthesizedParameterNames ParameterNameRenderingPolicy.NONE -> return false } } @@ -752,7 +753,7 @@ internal class DescriptorRendererImpl( renderAnnotations(primaryConstructor, builder, true) renderVisibility(primaryConstructor.getVisibility(), builder) builder.append("constructor") - renderValueParameters(primaryConstructor, builder) + renderValueParameters(primaryConstructor.valueParameters, primaryConstructor.hasSynthesizedParameterNames(), builder) } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/HtmlTabledDescriptorRenderer.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/HtmlTabledDescriptorRenderer.java index 53f9e76fe82..3d957e29740 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/HtmlTabledDescriptorRenderer.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/HtmlTabledDescriptorRenderer.java @@ -21,7 +21,6 @@ import kotlin.Unit; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer; import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.DescriptorRow; @@ -167,13 +166,17 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer { private static final DescriptorRenderer.ValueParametersHandler VALUE_PARAMETERS_HANDLER = new DescriptorRenderer.ValueParametersHandler() { @Override - public void appendBeforeValueParameter(@NotNull ValueParameterDescriptor parameter, @NotNull StringBuilder builder) { + public void appendBeforeValueParameter( + @NotNull ValueParameterDescriptor parameter, int parameterIndex, int parameterCount, @NotNull StringBuilder builder + ) { builder.append(""); } @Override - public void appendAfterValueParameter(@NotNull ValueParameterDescriptor parameter, @NotNull StringBuilder builder) { - boolean last = parameter.getContainingDeclaration().getValueParameters().size() - 1 == parameter.getIndex(); + public void appendAfterValueParameter( + @NotNull ValueParameterDescriptor parameter, int parameterIndex, int parameterCount, @NotNull StringBuilder builder + ) { + boolean last = parameterIndex == parameterCount - 1; if (!last) { builder.append(","); } @@ -181,9 +184,9 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer { } @Override - public void appendBeforeValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) { + public void appendBeforeValueParameters(int parameterCount, @NotNull StringBuilder builder) { builder.append(""); - if (function.getValueParameters().isEmpty()) { + if (parameterCount == 0) { tdBold(builder, "( )"); } else { @@ -192,8 +195,8 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer { } @Override - public void appendAfterValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) { - if (!function.getValueParameters().isEmpty()) { + public void appendAfterValueParameters(int parameterCount, @NotNull StringBuilder builder) { + if (parameterCount != 0) { tdBold(builder, ")"); } builder.append(""); diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt index d510e18864d..f61ba2df060 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt @@ -191,7 +191,7 @@ class BasicLookupElementFactory( } if (descriptor is CallableDescriptor) { - appendContainerAndReceiverInformation(descriptor) { tail, grayed -> element = element.appendTailText(tail, grayed) } + appendContainerAndReceiverInformation(descriptor) { element = element.appendTailText(it, true) } } if (descriptor is PropertyDescriptor) { @@ -215,13 +215,13 @@ class BasicLookupElementFactory( return element.withIconFromLookupObject() } - public fun appendContainerAndReceiverInformation(descriptor: CallableDescriptor, appendTailText: (String, Boolean) -> Unit) { + public fun appendContainerAndReceiverInformation(descriptor: CallableDescriptor, appendTailText: (String) -> Unit) { val extensionReceiver = descriptor.original.extensionReceiverParameter when { descriptor is SyntheticJavaPropertyDescriptor -> { var from = descriptor.getMethod.getName().asString() + "()" descriptor.setMethod?.let { from += "/" + it.getName().asString() + "()" } - appendTailText(" (from $from)", true) + appendTailText(" (from $from)") } // no need to show them as extensions @@ -230,7 +230,7 @@ class BasicLookupElementFactory( extensionReceiver != null -> { val receiverPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(extensionReceiver.type) - appendTailText(" for $receiverPresentation", true) + appendTailText(" for $receiverPresentation") val container = descriptor.getContainingDeclaration() val containerPresentation = if (container is ClassDescriptor) @@ -240,7 +240,7 @@ class BasicLookupElementFactory( else null if (containerPresentation != null) { - appendTailText(" in $containerPresentation", true) + appendTailText(" in $containerPresentation") } } @@ -249,7 +249,7 @@ class BasicLookupElementFactory( if (container is PackageFragmentDescriptor) { // we show container only for global functions and properties //TODO: it would be probably better to show it also for static declarations which are not from the current class (imported) - appendTailText(" (${container.fqName})", true) + appendTailText(" (${container.fqName})") } } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt index 5738a1e4d42..d93f019fd2c 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt @@ -28,15 +28,17 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.completion.handlers.GenerateLambdaInfo import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler -import org.jetbrains.kotlin.idea.completion.handlers.buildLambdaPresentation +import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.FuzzyType import org.jetbrains.kotlin.idea.util.fuzzyReturnType import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.JetProperty +import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor @@ -92,44 +94,55 @@ class LookupElementFactory( } private fun MutableCollection.addSpecialFunctionCallElements(descriptor: FunctionDescriptor, useReceiverTypes: Boolean) { - val singleParameter = descriptor.valueParameters.singleOrNull() ?: return - val parameterType = singleParameter.type + // check that all parameters except for the last one are optional + val lastParameter = descriptor.valueParameters.lastOrNull() ?: return + if (!descriptor.valueParameters.all { it == lastParameter || it.hasDefaultValue() }) return + val parameterType = lastParameter.type if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) { + val isSingleParameter = descriptor.valueParameters.size() == 1 + val functionParameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size() - if (functionParameterCount > 1) { - add(createFunctionCallElementWithExplicitLambdaParameters(descriptor, parameterType, useReceiverTypes)) + // we don't need special item inserting lambda for single functional parameter that does not need multiple arguments because the default item will be special in this case + if (!isSingleParameter || functionParameterCount > 1) { + add(createFunctionCallElementWithLambda(descriptor, parameterType, functionParameterCount > 1, useReceiverTypes)) } - //TODO: also ::function? at least for local functions - //TODO: order for them - val fuzzyParameterType = FuzzyType(parameterType, descriptor.typeParameters) - for (variable in functionTypeContextVariables) { - val substitutor = variable.fuzzyReturnType()?.checkIsSubtypeOf(fuzzyParameterType) - if (substitutor != null) { - val substitutedDescriptor = descriptor.substitute(substitutor) ?: continue - add(createFunctionCallElementWithArgument(substitutedDescriptor, variable.name.asString(), useReceiverTypes)) + if (isSingleParameter) { + //TODO: also ::function? at least for local functions + //TODO: order for them + val fuzzyParameterType = FuzzyType(parameterType, descriptor.typeParameters) + for (variable in functionTypeContextVariables) { + val substitutor = variable.fuzzyReturnType()?.checkIsSubtypeOf(fuzzyParameterType) + if (substitutor != null) { + val substitutedDescriptor = descriptor.substitute(substitutor) ?: continue + add(createFunctionCallElementWithArgument(substitutedDescriptor, variable.name.asString(), useReceiverTypes)) + } } } } } - private fun createFunctionCallElementWithExplicitLambdaParameters(descriptor: FunctionDescriptor, parameterType: JetType, useReceiverTypes: Boolean): LookupElement { + private fun createFunctionCallElementWithLambda(descriptor: FunctionDescriptor, parameterType: JetType, explicitLambdaParameters: Boolean, useReceiverTypes: Boolean): LookupElement { var lookupElement = createLookupElement(descriptor, useReceiverTypes) - val needTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler).inputTypeArguments - val lambdaInfo = GenerateLambdaInfo(parameterType, true) + val inputTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler).inputTypeArguments + val lambdaInfo = GenerateLambdaInfo(parameterType, explicitLambdaParameters) + val lambdaPresentation = lambdaPresentation(if (explicitLambdaParameters) parameterType else null) + + // render only the last parameter because all other should be optional and will be omitted + val parameterPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderValueParameters(listOf(descriptor.valueParameters.last()), descriptor.hasSynthesizedParameterNames()) lookupElement = object : LookupElementDecorator(lookupElement) { override fun renderElement(presentation: LookupElementPresentation) { super.renderElement(presentation) - val tails = presentation.getTailFragments() presentation.clearTail() - presentation.appendTailText(" " + buildLambdaPresentation(parameterType) + " ", false) - tails.forEach { presentation.appendTailText(it.text, true) } + presentation.appendTailText(" $lambdaPresentation ", false) + presentation.appendTailText(parameterPresentation, true) + basicFactory.appendContainerAndReceiverInformation(descriptor) { presentation.appendTailText(it, true) } } override fun handleInsert(context: InsertionContext) { - KotlinFunctionInsertHandler(needTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this) + KotlinFunctionInsertHandler(inputTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this) } } @@ -168,7 +181,7 @@ class LookupElementFactory( presentation.clearTail() presentation.appendTailText("($argumentText)", false) - basicFactory.appendContainerAndReceiverInformation(descriptor) { tail, grayed -> presentation.appendTailText(tail, grayed) } + basicFactory.appendContainerAndReceiverInformation(descriptor) { presentation.appendTailText(it, true) } } override fun handleInsert(context: InsertionContext) { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/GenerateLambda.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/GenerateLambda.kt index 0791b6438e6..6407fd0d9b9 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/GenerateLambda.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/GenerateLambda.kt @@ -64,7 +64,8 @@ fun insertLambdaTemplate(context: InsertionContext, placeholderRange: TextRange, } } -fun buildLambdaPresentation(lambdaType: JetType): String { +fun lambdaPresentation(lambdaType: JetType?): String { + if (lambdaType == null) return "{...}" val parameterTypes = functionParameterTypes(lambdaType) val parametersPresentation = parameterTypes.map { IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it) }.joinToString(", ") return "{ $parametersPresentation -> ... }" diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/LambdaItems.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/LambdaItems.kt index 216c9df9b5d..b3f166fa625 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/LambdaItems.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/LambdaItems.kt @@ -22,10 +22,10 @@ import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.idea.completion.ExpectedInfo import org.jetbrains.kotlin.idea.completion.fuzzyType -import org.jetbrains.kotlin.idea.completion.handlers.buildLambdaPresentation import org.jetbrains.kotlin.idea.completion.handlers.insertLambdaTemplate +import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation import org.jetbrains.kotlin.idea.completion.suppressAutoInsertion -import java.util.ArrayList +import java.util.* object LambdaItems { public fun collect(functionExpectedInfos: Collection): Collection { @@ -47,7 +47,7 @@ object LambdaItems { val singleSignatureLength = singleType?.let { KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(it).size() } val offerNoParametersLambda = singleSignatureLength == 0 || singleSignatureLength == 1 if (offerNoParametersLambda) { - val lookupElement = LookupElementBuilder.create("{...}") + val lookupElement = LookupElementBuilder.create(lambdaPresentation(null)) .withInsertHandler(ArtificialElementInsertHandler("{ ", " }", false)) .suppressAutoInsertion() .assignSmartCompletionPriority(SmartCompletionItemPriority.LAMBDA_NO_PARAMS) @@ -57,7 +57,7 @@ object LambdaItems { if (singleSignatureLength != 0) { for (functionType in distinctTypes) { - val lookupString = buildLambdaPresentation(functionType) + val lookupString = lambdaPresentation(functionType) val lookupElement = LookupElementBuilder.create(lookupString) .withInsertHandler({ context, lookupElement -> val offset = context.getStartOffset() diff --git a/idea/idea-completion/testData/basic/common/highOrderFunctions/OptionalParameters.kt b/idea/idea-completion/testData/basic/common/highOrderFunctions/OptionalParameters.kt new file mode 100644 index 00000000000..dcd502a27b5 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/highOrderFunctions/OptionalParameters.kt @@ -0,0 +1,25 @@ +fun xfoo1(option1: String = "", option2: Int = 1, p: () -> Unit){} +fun xfoo2(option1: String = "", option2: Int = 1, p: (Int) -> Boolean){} +fun xfoo3(option1: String = "", option2: Int = 1, p: (String, Char) -> Unit){} + +fun xfooBad1(option: String = "", notOption: Int, p: (String, Char) -> Unit){} +fun xfooBad2(option1: String = "", option2: Int = 1, p: (String, Char) -> Unit, option3: Int = 0){} + +fun test(param: () -> Unit) { + xfoo +} + +// EXIST: { itemText: "xfoo1", tailText: "(option1: String = ..., option2: Int = ..., p: () -> Unit) ()", typeText:"Unit" } +// EXIST: { itemText: "xfoo1", tailText: " {...} (p: () -> Unit) ()", typeText:"Unit" } + +// EXIST: { itemText: "xfoo2", tailText: "(option1: String = ..., option2: Int = ..., p: (Int) -> Boolean) ()", typeText:"Unit" } +// EXIST: { itemText: "xfoo2", tailText: " {...} (p: (Int) -> Boolean) ()", typeText:"Unit" } + +// EXIST: { itemText: "xfoo3", tailText: "(option1: String = ..., option2: Int = ..., p: (String, Char) -> Unit) ()", typeText:"Unit" } +// EXIST: { itemText: "xfoo3", tailText: " { String, Char -> ... } (p: (String, Char) -> Unit) ()", typeText:"Unit" } + +// EXIST: { itemText: "xfooBad1", tailText: "(option: String = ..., notOption: Int, p: (String, Char) -> Unit) ()", typeText:"Unit" } + +// EXIST: { itemText: "xfooBad2", tailText: "(option1: String = ..., option2: Int = ..., p: (String, Char) -> Unit, option3: Int = ...) ()", typeText:"Unit" } + +// NOTHING_ELSE \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt new file mode 100644 index 00000000000..9485e46305f --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt @@ -0,0 +1,9 @@ +fun xfoo(option1: String = "", option2: Int = 1, p: () -> Unit){} + +fun test(param: () -> Unit) { + xfoo +} + +// ELEMENT: xfoo +// TAIL_TEXT: " {...} (p: () -> Unit) ()" + diff --git a/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt.after b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt.after new file mode 100644 index 00000000000..3286dafef05 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt.after @@ -0,0 +1,9 @@ +fun xfoo(option1: String = "", option2: Int = 1, p: () -> Unit){} + +fun test(param: () -> Unit) { + xfoo { } +} + +// ELEMENT: xfoo +// TAIL_TEXT: " {...} (p: () -> Unit) ()" + diff --git a/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt new file mode 100644 index 00000000000..d0c855529b2 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt @@ -0,0 +1,9 @@ +fun xfoo(option1: String = "", option2: Int = 1, p: (String, Int) -> Unit){} + +fun test(param: () -> Unit) { + xfoo +} + +// ELEMENT: xfoo +// TAIL_TEXT: " { String, Int -> ... } (p: (String, Int) -> Unit) ()" + diff --git a/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt.after b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt.after new file mode 100644 index 00000000000..fe9c3c85bcb --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt.after @@ -0,0 +1,9 @@ +fun xfoo(option1: String = "", option2: Int = 1, p: (String, Int) -> Unit){} + +fun test(param: () -> Unit) { + xfoo { s, i -> } +} + +// ELEMENT: xfoo +// TAIL_TEXT: " { String, Int -> ... } (p: (String, Int) -> Unit) ()" + diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index c349dcc760e..24aaae80402 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -1364,6 +1364,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/HigherOrderFunction2.kt"); doTest(fileName); } + + @TestMetadata("OptionalParameters.kt") + public void testOptionalParameters() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/OptionalParameters.kt"); + doTest(fileName); + } } @TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature") diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index 128331c0796..d3478805bbf 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -1364,6 +1364,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/HigherOrderFunction2.kt"); doTest(fileName); } + + @TestMetadata("OptionalParameters.kt") + public void testOptionalParameters() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/OptionalParameters.kt"); + doTest(fileName); + } } @TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature") diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java index 0a74bfd05fe..03ffc4b3b67 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java @@ -274,6 +274,18 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("OptionalParameters1.kt") + public void testOptionalParameters1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt"); + doTest(fileName); + } + + @TestMetadata("OptionalParameters2.kt") + public void testOptionalParameters2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt"); + doTest(fileName); + } + @TestMetadata("ParameterTypeIsDerivedFromFunction.kt") public void testParameterTypeIsDerivedFromFunction() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/ParameterTypeIsDerivedFromFunction.kt");