From ee9389d08990d7c40dabf710e9ea136fe4e56c30 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 22 Dec 2015 12:59:39 +0300 Subject: [PATCH] Create from Usage: Strip first parameter of extension function when expected type is non-extension --- ...ateFunctionFromCallableReferenceActionFactory.kt | 10 +++++++--- .../nonExtensionWithReceiverInCallableRef.kt | 9 +++++++++ .../nonExtensionWithReceiverInCallableRef.kt.after | 13 +++++++++++++ .../kotlin/idea/quickfix/QuickFixTestGenerated.java | 6 ++++++ 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt create mode 100644 idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateFunctionFromCallableReferenceActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateFunctionFromCallableReferenceActionFactory.kt index eebb1ad1dbb..fd6edd97b7c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateFunctionFromCallableReferenceActionFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateFunctionFromCallableReferenceActionFactory.kt @@ -41,15 +41,19 @@ object CreateFunctionFromCallableReferenceActionFactory : CreateCallableMemberFr .guessTypes(context, resolutionFacade.moduleDescriptor) .filter { KotlinBuiltIns.isExactFunctionType(it) || KotlinBuiltIns.isExactExtensionFunctionType(it) } .mapNotNull { - val receiverTypeInfo = element.typeReference?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo.Empty + val expectedReceiverType = KotlinBuiltIns.getReceiverType(it) + val actualReceiverTypeRef = element.typeReference + val receiverTypeInfo = actualReceiverTypeRef?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo.Empty val returnTypeInfo = TypeInfo(KotlinBuiltIns.getReturnTypeFromFunctionType(it), Variance.OUT_VARIANCE) val containers = element.getExtractionContainers(includeAll = true).ifEmpty { return@mapNotNull null } val parameterInfos = SmartList().apply { - if (element.typeReference == null) { - KotlinBuiltIns.getReceiverType(it)?.let { add(ParameterInfo(TypeInfo(it, Variance.IN_VARIANCE))) } + if (actualReceiverTypeRef == null && expectedReceiverType != null) { + add(ParameterInfo(TypeInfo(expectedReceiverType, Variance.IN_VARIANCE))) } + KotlinBuiltIns .getParameterTypeProjectionsFromFunctionType(it) + .let { if (actualReceiverTypeRef != null && expectedReceiverType == null && it.isNotEmpty()) it.subList(1, it.size) else it } .mapTo(this) { ParameterInfo(TypeInfo(it.type, it.projectionKind)) } } diff --git a/idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt b/idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt new file mode 100644 index 00000000000..8cbaaaae613 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt @@ -0,0 +1,9 @@ +// "Create extension function 'foo'" "true" +// WITH_RUNTIME +fun T.map(f: (T) -> U) = f(this) + +fun consume(s: String) {} + +fun test() { + consume(1.map(Int::foo)) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt.after b/idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt.after new file mode 100644 index 00000000000..c0ce4f55868 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt.after @@ -0,0 +1,13 @@ +// "Create extension function 'foo'" "true" +// WITH_RUNTIME +fun T.map(f: (T) -> U) = f(this) + +fun consume(s: String) {} + +fun test() { + consume(1.map(Int::foo)) +} + +fun Int.foo(): String { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index aa8cb3101c4..4259a378e49 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -2228,6 +2228,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("nonExtensionWithReceiverInCallableRef.kt") + public void testNonExtensionWithReceiverInCallableRef() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/callableReferences/nonExtensionWithReceiverInCallableRef.kt"); + doTest(fileName); + } + @TestMetadata("withExpectedReturnType.kt") public void testWithExpectedReturnType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/callableReferences/withExpectedReturnType.kt");