Create from Usage: Strip first parameter of extension function when expected type is non-extension

This commit is contained in:
Alexey Sedunov
2015-12-22 12:59:39 +03:00
parent da2806acde
commit ee9389d089
4 changed files with 35 additions and 3 deletions
@@ -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<ParameterInfo>().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)) }
}
@@ -0,0 +1,9 @@
// "Create extension function 'foo'" "true"
// WITH_RUNTIME
fun <T, U> T.map(f: (T) -> U) = f(this)
fun consume(s: String) {}
fun test() {
consume(1.map(Int::<caret>foo))
}
@@ -0,0 +1,13 @@
// "Create extension function 'foo'" "true"
// WITH_RUNTIME
fun <T, U> T.map(f: (T) -> U) = f(this)
fun consume(s: String) {}
fun test() {
consume(1.map(Int::foo))
}
fun Int.foo(): String {
<selection>throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.</selection>
}
@@ -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");