From b9fab1123d57e67045efbaef1ae28ffe1c1041b4 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 27 May 2020 20:52:05 +0900 Subject: [PATCH] Convert lambda to reference: fix it works correctly for labeled expression #KT-37214 Fixed --- .../intentions/ConvertLambdaToReferenceIntention.kt | 12 ++++++++++-- .../convertLambdaToReference/labeledThis.kt | 13 +++++++++++++ .../convertLambdaToReference/labeledThis.kt.after | 11 +++++++++++ .../idea/intentions/IntentionTestGenerated.java | 5 +++++ 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 idea/testData/intentions/convertLambdaToReference/labeledThis.kt create mode 100644 idea/testData/intentions/convertLambdaToReference/labeledThis.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt index 2a63d9f94d6..67c1aebb8c9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt @@ -172,7 +172,7 @@ open class ConvertLambdaToReferenceIntention(textGetter: () -> String) : SelfTar override fun applyTo(element: KtLambdaExpression, editor: Editor?) { val referenceName = buildReferenceText(element) ?: return val factory = KtPsiFactory(element) - val lambdaArgument = element.parent as? KtLambdaArgument + val lambdaArgument = element.parentValueArgument() as? KtLambdaArgument if (lambdaArgument == null) { // Without lambda argument syntax, just replace lambda with reference val callableReferenceExpr = factory.createCallableReferenceExpression(referenceName) ?: return @@ -220,13 +220,21 @@ open class ConvertLambdaToReferenceIntention(textGetter: () -> String) : SelfTar companion object { private fun KtLambdaExpression.lambdaParameterType(context: BindingContext? = null): KotlinType? { - val argument = parent as? KtValueArgument ?: return null + val argument = parentValueArgument() ?: return null val callExpression = argument.getStrictParentOfType() ?: return null return callExpression .getResolvedCall(context ?: analyze(BodyResolveMode.PARTIAL)) ?.getParameterForArgument(argument)?.type } + private fun KtLambdaExpression.parentValueArgument(): KtValueArgument? { + return if (parent is KtLabeledExpression) { + parent.parent + } else { + parent + } as? KtValueArgument + } + private fun buildReferenceText(lambdaExpression: KtLambdaExpression, shortTypes: Boolean): String? { val lambdaParameterType = lambdaExpression.lambdaParameterType() return when (val singleStatement = lambdaExpression.singleStatementOrNull()) { diff --git a/idea/testData/intentions/convertLambdaToReference/labeledThis.kt b/idea/testData/intentions/convertLambdaToReference/labeledThis.kt new file mode 100644 index 00000000000..903cb82cee8 --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/labeledThis.kt @@ -0,0 +1,13 @@ +class A { + fun f1() {} +} + +fun myA(func: A.() -> Unit) { + A().func() +} + +fun main() { + myA foo@{ + this@foo.f1() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertLambdaToReference/labeledThis.kt.after b/idea/testData/intentions/convertLambdaToReference/labeledThis.kt.after new file mode 100644 index 00000000000..8606c5557f4 --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/labeledThis.kt.after @@ -0,0 +1,11 @@ +class A { + fun f1() {} +} + +fun myA(func: A.() -> Unit) { + A().func() +} + +fun main() { + myA(A::f1) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 7f7c08e3dff..83a20c21150 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -5065,6 +5065,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/convertLambdaToReference/inner.kt"); } + @TestMetadata("labeledThis.kt") + public void testLabeledThis() throws Exception { + runTest("idea/testData/intentions/convertLambdaToReference/labeledThis.kt"); + } + @TestMetadata("mapTo.kt") public void testMapTo() throws Exception { runTest("idea/testData/intentions/convertLambdaToReference/mapTo.kt");