Lambda to anonymous function: use callable builder (KT-7710)

This commit is contained in:
Mikhail Glukhikh
2018-05-10 21:08:11 +03:00
parent 8a20d1bf01
commit bd6fdb743c
9 changed files with 49 additions and 23 deletions
@@ -42,22 +42,32 @@ class LambdaToAnonymousFunctionIntention : SelfTargetingIntention<KtLambdaExpres
if (it.getTargetFunctionDescriptor(context) == descriptor) it.labeledExpression?.delete() if (it.getTargetFunctionDescriptor(context) == descriptor) it.labeledExpression?.delete()
} }
val extension = descriptor.extensionReceiverParameter?.type?.let { "$it." } ?: "" // TODO: check type rendering (!!!)
val params = descriptor.valueParameters.joinToString { "${it.name}: ${it.type}" } val anonymousFunction = psiFactory.createFunction(
val returnType = descriptor.returnType?.let { if (it.isUnit()) "" else ": $it" } ?: "" KtPsiFactory.CallableBuilder(KtPsiFactory.CallableBuilder.Target.FUNCTION).apply {
if (returnType.isNotEmpty()) { typeParams()
val lastStatement = bodyExpression.statements.lastOrNull() descriptor.extensionReceiverParameter?.type?.let {
if (lastStatement != null && lastStatement !is KtReturnExpression) { receiver(it.toString())
val foldableReturns = BranchedFoldingUtils.getFoldableReturns(lastStatement)
if (foldableReturns == null || foldableReturns.isEmpty()) {
lastStatement.replace(psiFactory.createExpressionByPattern("return $0", lastStatement))
} }
} name("")
} for (parameter in descriptor.valueParameters) {
val anonymousFunction = element.replaced( param(parameter.name.asString(), parameter.type.toString())
psiFactory.createExpressionByPattern("fun $0($1)$2 { $3 }", extension, params, returnType, bodyExpression, reformat = false) }
) as KtNamedFunction descriptor.returnType?.takeIf { !it.isUnit() }?.let {
val lastStatement = bodyExpression.statements.lastOrNull()
if (lastStatement != null && lastStatement !is KtReturnExpression) {
val foldableReturns = BranchedFoldingUtils.getFoldableReturns(lastStatement)
if (foldableReturns == null || foldableReturns.isEmpty()) {
lastStatement.replace(psiFactory.createExpressionByPattern("return $0", lastStatement))
}
}
returnType(it.toString())
} ?: noReturnType()
blockBody(" " + bodyExpression.text)
}.asString()
)
(anonymousFunction.parent as? KtLambdaArgument)?.also { it.moveInsideParentheses(it.analyze(BodyResolveMode.PARTIAL)) } val resultingFunction = element.replaced(anonymousFunction)
(resultingFunction.parent as? KtLambdaArgument)?.also { it.moveInsideParentheses(it.analyze(BodyResolveMode.PARTIAL)) }
} }
} }
@@ -1,5 +1,7 @@
fun foo(f: (Int) -> String) {} fun foo(f: (Int) -> String) {}
fun test() { fun test() {
foo(fun(it: Int): String { return "" }) foo(fun(it: Int): String {
return ""
})
} }
@@ -1,5 +1,7 @@
fun bar(f: (Int, Int) -> String) {} fun bar(f: (Int, Int) -> String) {}
fun test() { fun test() {
bar(fun(i: Int, j: Int): String { return "$i$j" }) bar(fun(i: Int, j: Int): String {
return "$i$j"
})
} }
@@ -2,5 +2,7 @@ class Foo
fun bar(f: Foo.() -> Unit) {} fun bar(f: Foo.() -> Unit) {}
fun main(args: Array<String>) { fun main(args: Array<String>) {
bar(fun Foo.() {}) bar(fun Foo.() {
})
} }
@@ -2,5 +2,7 @@ class Foo
fun baz(f: Foo.(i: Int, j: Int) -> Int) {} fun baz(f: Foo.(i: Int, j: Int) -> Int) {}
fun main(args: Array<String>) { fun main(args: Array<String>) {
baz(fun Foo.(i: Int, j: Int): Int { return i + j }) baz(fun Foo.(i: Int, j: Int): Int {
return i + j
})
} }
@@ -1,5 +1,7 @@
fun foo(f: (Int) -> String) {} fun foo(f: (Int) -> String) {}
fun test() { fun test() {
foo(fun(it: Int): String { return "$it" }) foo(fun(it: Int): String {
return "$it"
})
} }
@@ -1,5 +1,7 @@
fun foo(f: (Int) -> String) {} fun foo(f: (Int) -> String) {}
fun test() { fun test() {
foo(fun(it: Int): String { return "$it" }) foo(fun(it: Int): String {
return "$it"
})
} }
@@ -1,5 +1,7 @@
fun baz(name: String, f: (Int) -> String) {} fun baz(name: String, f: (Int) -> String) {}
fun test() { fun test() {
baz(name = "", f = fun(it: Int): String { return "$it" }) baz(name = "", f = fun(it: Int): String {
return "$it"
})
} }
@@ -1,5 +1,7 @@
fun foo(f: () -> String) {} fun foo(f: () -> String) {}
fun test() { fun test() {
foo(fun(): String { return "" }) foo(fun(): String {
return ""
})
} }