diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt index 7f8fcdea7c6..5460b289329 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt @@ -29,11 +29,13 @@ import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes +import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext.FUNCTION import org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue +import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.types.isError @@ -222,10 +224,13 @@ open class ConvertLambdaToReferenceIntention(text: String) : val calleeReferenceExpression = singleStatement.calleeExpression as? KtNameReferenceExpression ?: return null val context = singleStatement.analyze() val resolvedCall = calleeReferenceExpression.getResolvedCall(context) ?: return null - if (resolvedCall.dispatchReceiver != null || resolvedCall.extensionReceiver != null) - "this::${singleStatement.getCallReferencedName()}" - else - "::${singleStatement.getCallReferencedName()}" + val receiver = resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver + val receiverText = when { + receiver == null -> "" + lambdaExpression.getResolutionScope().getImplicitReceiversHierarchy().size == 1 -> "this" + else -> receiver.type.constructor.declarationDescriptor?.name?.let { "this@$it" } ?: return null + } + "$receiverText::${singleStatement.getCallReferencedName()}" } is KtDotQualifiedExpression -> { val selector = singleStatement.selectorExpression diff --git a/idea/testData/intentions/convertLambdaToReference/extentionOuterScope.kt b/idea/testData/intentions/convertLambdaToReference/extentionOuterScope.kt new file mode 100644 index 00000000000..e7e56426bce --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/extentionOuterScope.kt @@ -0,0 +1,13 @@ +// IS_APPLICABLE: true +// WITH_RUNTIME + +class Test { + fun test() { + with(Any()) { + val f = { s: String -> foo(s) } + } + } + +} + +fun Test.foo(s: String) {} \ No newline at end of file diff --git a/idea/testData/intentions/convertLambdaToReference/extentionOuterScope.kt.after b/idea/testData/intentions/convertLambdaToReference/extentionOuterScope.kt.after new file mode 100644 index 00000000000..f634f7f38dd --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/extentionOuterScope.kt.after @@ -0,0 +1,13 @@ +// IS_APPLICABLE: true +// WITH_RUNTIME + +class Test { + fun test() { + with(Any()) { + val f = this@Test::foo + } + } + +} + +fun Test.foo(s: String) {} \ No newline at end of file diff --git a/idea/testData/intentions/convertLambdaToReference/memberOuterScope.kt b/idea/testData/intentions/convertLambdaToReference/memberOuterScope.kt new file mode 100644 index 00000000000..6ace8347cbb --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/memberOuterScope.kt @@ -0,0 +1,11 @@ +// IS_APPLICABLE: true +// WITH_RUNTIME + +class Test { + fun test() { + with(Any()) { + val f = { s: String -> foo(s) } + } + } + fun foo(s: String) {} +} \ No newline at end of file diff --git a/idea/testData/intentions/convertLambdaToReference/memberOuterScope.kt.after b/idea/testData/intentions/convertLambdaToReference/memberOuterScope.kt.after new file mode 100644 index 00000000000..a6039ae7920 --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/memberOuterScope.kt.after @@ -0,0 +1,11 @@ +// IS_APPLICABLE: true +// WITH_RUNTIME + +class Test { + fun test() { + with(Any()) { + val f = this@Test::foo + } + } + fun foo(s: String) {} +} \ 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 b118cf98e6f..99b29767d3a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -5120,6 +5120,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("extentionOuterScope.kt") + public void testExtentionOuterScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertLambdaToReference/extentionOuterScope.kt"); + doTest(fileName); + } + @TestMetadata("fqNameForReceiver.kt") public void testFqNameForReceiver() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertLambdaToReference/fqNameForReceiver.kt"); @@ -5198,6 +5204,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("memberOuterScope.kt") + public void testMemberOuterScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertLambdaToReference/memberOuterScope.kt"); + doTest(fileName); + } + @TestMetadata("memberViaThis.kt") public void testMemberViaThis() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertLambdaToReference/memberViaThis.kt");