KT-12669 Completion should show variant with () when there is default lambda

#KT-12669
This commit is contained in:
Valentin Kipyatkov
2016-06-16 21:01:46 +03:00
parent 962a8f9bf4
commit eb1dbfc652
6 changed files with 37 additions and 6 deletions
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.core.ExpectedInfo
import org.jetbrains.kotlin.idea.core.fuzzyType import org.jetbrains.kotlin.idea.core.fuzzyType
import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.idea.util.CallType
import org.jetbrains.kotlin.idea.util.fuzzyReturnType import org.jetbrains.kotlin.idea.util.fuzzyReturnType
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.getValueParametersCountFromFunctionType import org.jetbrains.kotlin.resolve.getValueParametersCountFromFunctionType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import java.util.* import java.util.*
@@ -48,9 +49,10 @@ class InsertHandlerProvider(
1 -> { 1 -> {
if (callType != CallType.SUPER_MEMBERS) { // for super call we don't suggest to generate "super.foo { ... }" (seems to be non-typical use) if (callType != CallType.SUPER_MEMBERS) { // for super call we don't suggest to generate "super.foo { ... }" (seems to be non-typical use)
val parameterType = parameters.single().type val parameter = parameters.single()
val parameterType = parameter.type
if (parameterType.isFunctionType) { if (parameterType.isFunctionType) {
if (getValueParametersCountFromFunctionType(parameterType) <= 1) { if (getValueParametersCountFromFunctionType(parameterType) <= 1 && !parameter.hasDefaultValue()) {
// otherwise additional item with lambda template is to be added // otherwise additional item with lambda template is to be added
return KotlinFunctionInsertHandler.Normal( return KotlinFunctionInsertHandler.Normal(
callType, needTypeArguments, inputValueArguments = false, callType, needTypeArguments, inputValueArguments = false,
@@ -140,9 +140,9 @@ class LookupElementFactory(
val isSingleParameter = descriptor.valueParameters.size == 1 val isSingleParameter = descriptor.valueParameters.size == 1
val parameterType = lastParameter.type val parameterType = lastParameter.type
val functionParameterCount = getValueParametersCountFromFunctionType(parameterType) val insertHandler = insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler.Normal
// 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 (insertHandler.lambdaInfo == null) {
if (!isSingleParameter || functionParameterCount > 1) { val functionParameterCount = getValueParametersCountFromFunctionType(parameterType)
add(createFunctionCallElementWithLambda(descriptor, parameterType, functionParameterCount > 1, useReceiverTypes)) add(createFunctionCallElementWithLambda(descriptor, parameterType, functionParameterCount > 1, useReceiverTypes))
} }
@@ -210,7 +210,7 @@ class LookupElementFactory(
} }
private fun createFunctionCallElementWithArguments(descriptor: FunctionDescriptor, argumentText: String, useReceiverTypes: Boolean): LookupElement { private fun createFunctionCallElementWithArguments(descriptor: FunctionDescriptor, argumentText: String, useReceiverTypes: Boolean): LookupElement {
var lookupElement = createLookupElement(descriptor, useReceiverTypes) val lookupElement = createLookupElement(descriptor, useReceiverTypes)
val needTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler.Normal).inputTypeArguments val needTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler.Normal).inputTypeArguments
return FunctionCallWithArgumentsLookupElement(lookupElement, descriptor, argumentText, needTypeArguments) return FunctionCallWithArgumentsLookupElement(lookupElement, descriptor, argumentText, needTypeArguments)
@@ -1,6 +1,7 @@
fun xfoo1(option1: String = "", option2: Int = 1, p: () -> Unit){} fun xfoo1(option1: String = "", option2: Int = 1, p: () -> Unit){}
fun xfoo2(option1: String = "", option2: Int = 1, p: (Int) -> Boolean){} fun xfoo2(option1: String = "", option2: Int = 1, p: (Int) -> Boolean){}
fun xfoo3(option1: String = "", option2: Int = 1, p: (String, Char) -> Unit){} fun xfoo3(option1: String = "", option2: Int = 1, p: (String, Char) -> Unit){}
fun xfoo4(p: () -> Unit = {}){}
fun xfooBad1(option: String = "", notOption: Int, 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 xfooBad2(option1: String = "", option2: Int = 1, p: (String, Char) -> Unit, option3: Int = 0){}
@@ -18,6 +19,10 @@ fun test(param: () -> Unit) {
// EXIST: { itemText: "xfoo3", tailText: "(option1: String = ..., option2: Int = ..., p: (String, Char) -> Unit) (<root>)", typeText:"Unit" } // EXIST: { itemText: "xfoo3", tailText: "(option1: String = ..., option2: Int = ..., p: (String, Char) -> Unit) (<root>)", typeText:"Unit" }
// EXIST: { itemText: "xfoo3", tailText: " { String, Char -> ... } (..., p: (String, Char) -> Unit) (<root>)", typeText:"Unit" } // EXIST: { itemText: "xfoo3", tailText: " { String, Char -> ... } (..., p: (String, Char) -> Unit) (<root>)", typeText:"Unit" }
// EXIST: { itemText: "xfoo4", tailText: "(p: () -> Unit = ...) (<root>)", typeText:"Unit" }
// EXIST: { itemText: "xfoo4", tailText: " {...} (p: () -> Unit = ...) (<root>)", typeText:"Unit" }
// EXIST: { itemText: "xfoo4", tailText: "(param) (<root>)", typeText:"Unit" }
// EXIST: { itemText: "xfooBad1", tailText: "(option: String = ..., notOption: Int, p: (String, Char) -> Unit) (<root>)", typeText:"Unit" } // EXIST: { itemText: "xfooBad1", tailText: "(option: String = ..., notOption: Int, p: (String, Char) -> Unit) (<root>)", typeText:"Unit" }
// EXIST: { itemText: "xfooBad2", tailText: "(option1: String = ..., option2: Int = ..., p: (String, Char) -> Unit, option3: Int = ...) (<root>)", typeText:"Unit" } // EXIST: { itemText: "xfooBad2", tailText: "(option1: String = ..., option2: Int = ..., p: (String, Char) -> Unit, option3: Int = ...) (<root>)", typeText:"Unit" }
@@ -0,0 +1,9 @@
fun xfoo(p: () -> Unit = {}){}
fun test() {
xfo<caret>
}
// ELEMENT: xfoo
// TAIL_TEXT: " {...} (p: () -> Unit = ...) (<root>)"
@@ -0,0 +1,9 @@
fun xfoo(p: () -> Unit = {}){}
fun test() {
xfoo { <caret> }
}
// ELEMENT: xfoo
// TAIL_TEXT: " {...} (p: () -> Unit = ...) (<root>)"
@@ -385,6 +385,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
doTest(fileName); doTest(fileName);
} }
@TestMetadata("OptionalParameters3.kt")
public void testOptionalParameters3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters3.kt");
doTest(fileName);
}
@TestMetadata("ParameterTypeIsDerivedFromFunction.kt") @TestMetadata("ParameterTypeIsDerivedFromFunction.kt")
public void testParameterTypeIsDerivedFromFunction() throws Exception { public void testParameterTypeIsDerivedFromFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/ParameterTypeIsDerivedFromFunction.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/ParameterTypeIsDerivedFromFunction.kt");