Convert reference to lambda: fix it works correctly when referenced function has default argument
#KT-17222 Fixed #KT-24138 Fixed #KT-39532
This commit is contained in:
committed by
Roman Golyshev
parent
bc34f7f7f5
commit
2fd3af73eb
+20
-15
@@ -37,27 +37,32 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio
|
||||
val context = element.analyze(BodyResolveMode.PARTIAL)
|
||||
val reference = element.callableReference
|
||||
val targetDescriptor = context[REFERENCE_TARGET, reference] as? CallableMemberDescriptor ?: return
|
||||
val parameterNamesAndTypes = targetDescriptor.valueParameters.map { it.name.asString() to it.type }
|
||||
val receiverExpression = element.receiverExpression
|
||||
val receiverType = receiverExpression?.let {
|
||||
(context[DOUBLE_COLON_LHS, it] as? DoubleColonLHS.Type)?.type
|
||||
}
|
||||
|
||||
val receiverNameAndType = receiverType?.let {
|
||||
KotlinNameSuggester.suggestNamesByType(it, validator = { name ->
|
||||
name !in parameterNamesAndTypes.map { pair -> pair.first }
|
||||
}, defaultName = "receiver").first() to it
|
||||
}
|
||||
|
||||
val valueArgumentParent = element.parent as? KtValueArgument
|
||||
val callGrandParent = valueArgumentParent?.parent?.parent as? KtCallExpression
|
||||
val resolvedCall = callGrandParent?.getResolvedCall(context)
|
||||
val matchingParameterType = resolvedCall?.getParameterForArgument(valueArgumentParent)?.type
|
||||
val matchingParameterIsExtension = matchingParameterType?.isExtensionFunctionType ?: false
|
||||
|
||||
val acceptsReceiverAsParameter = receiverNameAndType != null && !matchingParameterIsExtension &&
|
||||
(targetDescriptor.dispatchReceiverParameter != null ||
|
||||
targetDescriptor.extensionReceiverParameter != null)
|
||||
val receiverExpression = element.receiverExpression
|
||||
val receiverType = receiverExpression?.let {
|
||||
(context[DOUBLE_COLON_LHS, it] as? DoubleColonLHS.Type)?.type
|
||||
}
|
||||
val acceptsReceiverAsParameter = receiverType != null && !matchingParameterIsExtension &&
|
||||
(targetDescriptor.dispatchReceiverParameter != null || targetDescriptor.extensionReceiverParameter != null)
|
||||
|
||||
val parameterNamesAndTypes = targetDescriptor.valueParameters.map { it.name.asString() to it.type }.let {
|
||||
if (matchingParameterType != null) {
|
||||
val parameterSize = matchingParameterType.arguments.size - (if (acceptsReceiverAsParameter) 2 else 1)
|
||||
if (parameterSize >= 0) it.take(parameterSize) else it
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
val receiverNameAndType = receiverType?.let {
|
||||
KotlinNameSuggester.suggestNamesByType(it, validator = { name ->
|
||||
name !in parameterNamesAndTypes.map { pair -> pair.first }
|
||||
}, defaultName = "receiver").first() to it
|
||||
}
|
||||
|
||||
val factory = KtPsiFactory(element)
|
||||
val targetName = reference.text
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
fun test() {
|
||||
foo1(<caret>::convert2)
|
||||
}
|
||||
|
||||
fun foo1(convert: (Int) -> Unit) {}
|
||||
|
||||
fun convert2(i: Int, j: Int = 0) {}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fun test() {
|
||||
foo1 { convert2(it) }
|
||||
}
|
||||
|
||||
fun foo1(convert: (Int) -> Unit) {}
|
||||
|
||||
fun convert2(i: Int, j: Int = 0) {}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fun test() {
|
||||
foo2(<caret>::convert3)
|
||||
}
|
||||
|
||||
fun foo2(convert: (Int, Int) -> Unit) {}
|
||||
|
||||
fun convert3(i: Int, j: Int, k: Int = 0) {}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fun test() {
|
||||
foo2 { i, j -> convert3(i, j) }
|
||||
}
|
||||
|
||||
fun foo2(convert: (Int, Int) -> Unit) {}
|
||||
|
||||
fun convert3(i: Int, j: Int, k: Int = 0) {}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fun test() {
|
||||
bar(<caret>Int::foo)
|
||||
}
|
||||
|
||||
fun Int.foo(x: Int, y: Int = 42) = x + y
|
||||
|
||||
fun bar(f: (Int, Int) -> Int) {}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fun test() {
|
||||
bar { i, x -> i.foo(x) }
|
||||
}
|
||||
|
||||
fun Int.foo(x: Int, y: Int = 42) = x + y
|
||||
|
||||
fun bar(f: (Int, Int) -> Int) {}
|
||||
@@ -6500,6 +6500,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
runTest("idea/testData/intentions/convertReferenceToLambda/receiverParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referencedFunctionWithDefaultArugment.kt")
|
||||
public void testReferencedFunctionWithDefaultArugment() throws Exception {
|
||||
runTest("idea/testData/intentions/convertReferenceToLambda/referencedFunctionWithDefaultArugment.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referencedFunctionWithDefaultArugment2.kt")
|
||||
public void testReferencedFunctionWithDefaultArugment2() throws Exception {
|
||||
runTest("idea/testData/intentions/convertReferenceToLambda/referencedFunctionWithDefaultArugment2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referencedFunctionWithDefaultArugment3.kt")
|
||||
public void testReferencedFunctionWithDefaultArugment3() throws Exception {
|
||||
runTest("idea/testData/intentions/convertReferenceToLambda/referencedFunctionWithDefaultArugment3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("idea/testData/intentions/convertReferenceToLambda/simple.kt");
|
||||
|
||||
Reference in New Issue
Block a user