"Convert reference to lambda" intention: handle extension function reference with extension function call

#KT-35558 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-12-19 19:53:51 +09:00
committed by igoriakovlev
parent 9ff7539ff0
commit b1e8238ea2
8 changed files with 81 additions and 4 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
@@ -42,6 +43,7 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio
val resolvedCall = callGrandParent?.getResolvedCall(context)
val matchingParameterType = resolvedCall?.getParameterForArgument(valueArgumentParent)?.type
val matchingParameterIsExtension = matchingParameterType?.isExtensionFunctionType ?: false
val firstArgumentIsThis = matchingParameterIsExtension && resolvedCall?.resultingDescriptor?.isExtension == true
val receiverExpression = element.receiverExpression
val receiverType = receiverExpression?.let {
@@ -87,23 +89,29 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio
if (targetDescriptor is PropertyDescriptor) "it.$targetName"
else "it.$targetName()"
else ->
"$receiverPrefix$targetName(it)"
"$receiverPrefix$targetName(${if (firstArgumentIsThis) "this" else "it"})"
}
)
} else {
val (lambdaParams, args) = if (firstArgumentIsThis) {
val thisArgument = if (parameterNamesAndTypes.isNotEmpty()) listOf("this") else emptyList()
lambdaParameterNamesAndTypes.drop(1) to (thisArgument + parameterNamesAndTypes.drop(1).map { it.first })
} else {
lambdaParameterNamesAndTypes to parameterNamesAndTypes.map { it.first }
}
factory.createLambdaExpression(
parameters = lambdaParameterNamesAndTypes.joinToString(separator = ", ") {
parameters = lambdaParams.joinToString(separator = ", ") {
if (valueArgumentParent != null) it.first
else it.first + ": " + SOURCE_RENDERER.renderType(it.second)
},
body = if (targetDescriptor is PropertyDescriptor) {
"$receiverPrefix$targetName"
} else {
parameterNamesAndTypes.joinToString(
args.joinToString(
prefix = "$receiverPrefix$targetName(",
separator = ", ",
postfix = ")"
) { it.first }
)
}
)
}
@@ -0,0 +1,9 @@
fun func(a: Int) {
}
fun Int.foo(block: (Int) -> Unit) {
}
fun main() {
42.foo(::func<caret>)
}
@@ -0,0 +1,9 @@
fun func(a: Int) {
}
fun Int.foo(block: (Int) -> Unit) {
}
fun main() {
42.foo { func(it) }
}
@@ -0,0 +1,9 @@
fun func(a: Int) {
}
fun Int.foo(block: Int.() -> Unit) {
}
fun main() {
42.foo(::func<caret>)
}
@@ -0,0 +1,9 @@
fun func(a: Int) {
}
fun Int.foo(block: Int.() -> Unit) {
}
fun main() {
42.foo { func(this) }
}
@@ -0,0 +1,9 @@
fun func2(a: Int, b: Int) {
}
fun Int.foo(block: Int.(Int) -> Unit) {
}
fun main() {
42.foo(::func2<caret>)
}
@@ -0,0 +1,9 @@
fun func2(a: Int, b: Int) {
}
fun Int.foo(block: Int.(Int) -> Unit) {
}
fun main() {
42.foo { b -> func2(this, b) }
}
@@ -6455,6 +6455,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/convertReferenceToLambda/extensionFunctionalType.kt");
}
@TestMetadata("extensionFunctionalType2.kt")
public void testExtensionFunctionalType2() throws Exception {
runTest("idea/testData/intentions/convertReferenceToLambda/extensionFunctionalType2.kt");
}
@TestMetadata("extensionFunctionalType3.kt")
public void testExtensionFunctionalType3() throws Exception {
runTest("idea/testData/intentions/convertReferenceToLambda/extensionFunctionalType3.kt");
}
@TestMetadata("extensionFunctionalType4.kt")
public void testExtensionFunctionalType4() throws Exception {
runTest("idea/testData/intentions/convertReferenceToLambda/extensionFunctionalType4.kt");
}
@TestMetadata("extensionProperty.kt")
public void testExtensionProperty() throws Exception {
runTest("idea/testData/intentions/convertReferenceToLambda/extensionProperty.kt");