From 70b202dfa65b364556b8d2ad9c5863f871c1cc86 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Wed, 14 Jan 2015 14:01:29 +0300 Subject: [PATCH] Extract Function: Do not extract extension receiver from 'implicit invoke' call #KT-6302 Fixed --- .../extractFunction/extractableAnalysisUtil.kt | 16 +++++++++------- .../misc/extensionLambdaAsParameter.kt | 8 ++++++++ .../misc/extensionLambdaAsParameter.kt.after | 12 ++++++++++++ .../JetExtractionTestGenerated.java | 6 ++++++ 4 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt create mode 100644 idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/extractFunction/extractableAnalysisUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/extractFunction/extractableAnalysisUtil.kt index 46f05260bee..14e2be1147a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/extractFunction/extractableAnalysisUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/extractFunction/extractableAnalysisUtil.kt @@ -68,6 +68,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.idea.refactoring.comparePossiblyOverridingDescriptors import org.jetbrains.kotlin.idea.util.makeNullable +import org.jetbrains.kotlin.resolve.calls.CallTransformer private val DEFAULT_FUNCTION_NAME = "myFun" private val DEFAULT_RETURN_TYPE = KotlinBuiltIns.getInstance().getUnitType() @@ -567,13 +568,14 @@ private fun ExtractionData.inferParametersInfo( return info } - val receiverArgument = resolvedCall?.getExtensionReceiver() - val receiver = when(receiverArgument) { - ReceiverValue.NO_RECEIVER -> resolvedCall?.getDispatchReceiver() - else -> receiverArgument - } ?: ReceiverValue.NO_RECEIVER + val extensionReceiver = resolvedCall?.getExtensionReceiver() + val receiverToExtract = when { + extensionReceiver == ReceiverValue.NO_RECEIVER, + resolvedCall?.getCall() is CallTransformer.CallForImplicitInvoke -> resolvedCall?.getDispatchReceiver() + else -> extensionReceiver + } ?: ReceiverValue.NO_RECEIVER - val thisDescriptor = (receiver as? ThisReceiver)?.getDeclarationDescriptor() + val thisDescriptor = (receiverToExtract as? ThisReceiver)?.getDeclarationDescriptor() val hasThisReceiver = thisDescriptor != null val thisExpr = ref.getParent() as? JetThisExpression @@ -611,7 +613,7 @@ private fun ExtractionData.inferParametersInfo( val extractParameter = extractThis || extractLocalVar if (extractParameter) { val parameterType = when { - receiver.exists() -> receiver.getType() + receiverToExtract.exists() -> receiverToExtract.getType() else -> bindingContext[BindingContext.SMARTCAST, originalRef] ?: bindingContext[BindingContext.EXPRESSION_TYPE, originalRef] ?: DEFAULT_PARAMETER_TYPE diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt b/idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt new file mode 100644 index 00000000000..d38a530b44e --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt @@ -0,0 +1,8 @@ +// PARAM_TYPES: kotlin.String.() -> T +// PARAM_DESCRIPTOR: value-parameter val f: kotlin.String.() -> T defined in test +fun test(f: String.() -> T): T { + while (true) { + val answer = "Hey!".f() + return answer + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt.after b/idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt.after new file mode 100644 index 00000000000..6d3bebfb81b --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt.after @@ -0,0 +1,12 @@ +// PARAM_TYPES: kotlin.String.() -> T +// PARAM_DESCRIPTOR: value-parameter val f: kotlin.String.() -> T defined in test +fun test(f: String.() -> T): T { + return t(f) +} + +private fun t(f: String.() -> T): T { + while (true) { + val answer = "Hey!".f() + return answer + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java index f10d6e4fbf6..6ce8edd3c54 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java @@ -1694,6 +1694,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest(fileName); } + @TestMetadata("extensionLambdaAsParameter.kt") + public void testExtensionLambdaAsParameter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/misc/extensionLambdaAsParameter.kt"); + doExtractFunctionTest(fileName); + } + @TestMetadata("innerClassObject.kt") public void testInnerClassObject() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/misc/innerClassObject.kt");