"Convert anonymous function to lambda expression" intention: add necessary lambda type parameter

#KT-37748 Fixed
This commit is contained in:
Toshiaki Kameyama
2020-04-03 17:37:38 +09:00
committed by igoriakovlev
parent d27c7ce86f
commit 46ab338ea6
9 changed files with 83 additions and 1 deletions
@@ -9,7 +9,9 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.core.getLastLambdaExpression
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParenthesesIfPossible
import org.jetbrains.kotlin.idea.core.replaced
@@ -17,8 +19,10 @@ import org.jetbrains.kotlin.idea.util.CommentSaver
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.contentRange
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class AnonymousFunctionToLambdaIntention : SelfTargetingRangeIntention<KtNamedFunction>(
@@ -40,6 +44,14 @@ class AnonymousFunctionToLambdaIntention : SelfTargetingRangeIntention<KtNamedFu
}
override fun applyTo(element: KtNamedFunction, editor: Editor?) {
val argument = element.getStrictParentOfType<KtValueArgument>() ?: return
val callElement = argument.getStrictParentOfType<KtCallElement>() ?: return
val functionParameterTypes = if (callElement.typeArgumentList == null) {
callElement.resolveToCall()?.getParameterForArgument(argument)?.original?.type?.arguments.orEmpty()
} else {
emptyList()
}
val commentSaver = CommentSaver(element)
val returnSaver = ReturnSaver(element)
@@ -58,6 +70,13 @@ class AnonymousFunctionToLambdaIntention : SelfTargetingRangeIntention<KtNamedFu
appendFixedText(",")
}
appendName(parameter.nameAsSafeName)
val needParameterType =
functionParameterTypes.getOrNull(index)?.type?.constructor?.declarationDescriptor is TypeParameterDescriptor
val typeReference = parameter.typeReference
if (needParameterType && typeReference != null) {
appendFixedText(": ")
appendTypeReference(typeReference)
}
}
appendFixedText("->")
@@ -0,0 +1,9 @@
fun foo(p: String) {}
fun <T> bar(fn: (T) -> Unit) {}
fun test() {
bar(<caret>fun(x: String) {
foo(x)
})
}
@@ -0,0 +1,7 @@
fun foo(p: String) {}
fun <T> bar(fn: (T) -> Unit) {}
fun test() {
bar { x: String -> foo(x) }
}
@@ -0,0 +1,9 @@
fun foo(p: String, q: Int, r: Long) {}
fun <T, U> bar(fn: (T, Int, U) -> Unit) {}
fun test() {
bar(<caret>fun(x: String, y: Int, z: Long) {
foo(x, y, z)
})
}
@@ -0,0 +1,7 @@
fun foo(p: String, q: Int, r: Long) {}
fun <T, U> bar(fn: (T, Int, U) -> Unit) {}
fun test() {
bar { x: String, y, z: Long -> foo(x, y, z) }
}
@@ -0,0 +1,9 @@
fun foo(p: String) {}
fun <T> bar(fn: (T) -> Unit) {}
fun test() {
bar<String>(<caret>fun(x: String) {
foo(x)
})
}
@@ -0,0 +1,7 @@
fun foo(p: String) {}
fun <T> bar(fn: (T) -> Unit) {}
fun test() {
bar<String> { x -> foo(x) }
}
@@ -2100,6 +2100,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
public void testSimple() throws Exception {
runTest("idea/testData/intentions/anonymousFunctionToLambda/simple.kt");
}
@TestMetadata("typeParameter.kt")
public void testTypeParameter() throws Exception {
runTest("idea/testData/intentions/anonymousFunctionToLambda/typeParameter.kt");
}
@TestMetadata("typeParameter2.kt")
public void testTypeParameter2() throws Exception {
runTest("idea/testData/intentions/anonymousFunctionToLambda/typeParameter2.kt");
}
@TestMetadata("typeParameter3.kt")
public void testTypeParameter3() throws Exception {
runTest("idea/testData/intentions/anonymousFunctionToLambda/typeParameter3.kt");
}
}
@TestMetadata("idea/testData/intentions/branched")
@@ -12,7 +12,7 @@ class TestJava {
@JvmStatic
fun main(args: Array<String>) {
val x = ArrayList<String>()
x.filter { o -> o == "a" }
x.filter { o: String -> o == "a" }
val lazy = lazy(LazyThreadSafetyMode.NONE) { "aaa" }
}
}