Convert reference to lambda: correct handling of static method references #KT-14982 Fixed
This commit is contained in:
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
|
||||
class ConvertReferenceToLambdaInspection : IntentionBasedInspection<KtCallableReferenceExpression>(ConvertReferenceToLambdaIntention::class)
|
||||
|
||||
@@ -51,23 +50,31 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio
|
||||
val receiverNameAndType = receiverType?.let { KotlinNameSuggester.suggestNamesByType(it, validator = {
|
||||
name -> name !in parameterNamesAndTypes.map { it.first }
|
||||
}, defaultName = "receiver").first() to it }
|
||||
val acceptsReceiverAsParameter = receiverNameAndType != null &&
|
||||
(targetDescriptor.dispatchReceiverParameter != null ||
|
||||
targetDescriptor.extensionReceiverParameter != null)
|
||||
|
||||
val referenceParent = element.parent
|
||||
val insideCall = referenceParent is KtValueArgument
|
||||
|
||||
val factory = KtPsiFactory(element)
|
||||
val targetName = reference.text
|
||||
val lambdaParameterNamesAndTypes = receiverNameAndType.singletonOrEmptyList() + parameterNamesAndTypes
|
||||
val receiverPrefix = receiverNameAndType?.let { it.first + "." } ?: ""
|
||||
val lambdaParameterNamesAndTypes =
|
||||
if (acceptsReceiverAsParameter) listOf(receiverNameAndType!!) + parameterNamesAndTypes
|
||||
else parameterNamesAndTypes
|
||||
|
||||
val receiverPrefix =
|
||||
if (acceptsReceiverAsParameter) receiverNameAndType!!.first + "."
|
||||
else receiverExpression?.let { it.text + "." } ?: ""
|
||||
val lambdaExpression = if (insideCall && lambdaParameterNamesAndTypes.size == 1) {
|
||||
factory.createLambdaExpression(
|
||||
parameters = "",
|
||||
body = when {
|
||||
receiverNameAndType != null ->
|
||||
acceptsReceiverAsParameter ->
|
||||
if (targetDescriptor is PropertyDescriptor) "it.$targetName"
|
||||
else "it.$targetName()"
|
||||
else ->
|
||||
"$targetName(it)"
|
||||
"$receiverPrefix$targetName(it)"
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
import Utils.Companion.foo
|
||||
|
||||
val list = listOf(1, 2, 3).map(<caret>::foo)
|
||||
|
||||
class Utils {
|
||||
companion object {
|
||||
fun foo(x: Int) = x
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
import Utils.Companion.foo
|
||||
|
||||
val list = listOf(1, 2, 3).map { foo(it) }
|
||||
|
||||
class Utils {
|
||||
companion object {
|
||||
fun foo(x: Int) = x
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// IS_APPLICABLE: false
|
||||
// WITH_RUNTIME
|
||||
val list = listOf(1, 2, 3).map(<caret>Utils::foo)
|
||||
|
||||
object Utils {
|
||||
fun foo(x: Int) = x
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class Utils {
|
||||
public static int foo(int arg) { return arg; }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class Utils {
|
||||
public static int foo(int arg) { return arg; }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// WITH_RUNTIME
|
||||
val list = listOf(1, 2, 3).map(<caret>Utils::foo)
|
||||
@@ -0,0 +1,2 @@
|
||||
// WITH_RUNTIME
|
||||
val list = listOf(1, 2, 3).map { Utils.foo(it) }
|
||||
@@ -0,0 +1,3 @@
|
||||
class Utils {
|
||||
public static int foo(int x, int y) { return x + y; }
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
class Utils {
|
||||
public static int foo(int x, int y) { return x + y; }
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
val x = <caret>Utils::foo
|
||||
+1
@@ -0,0 +1 @@
|
||||
val x = { x: Int, y: Int -> Utils.foo(x, y) }
|
||||
@@ -4967,6 +4967,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("companion.kt")
|
||||
public void testCompanion() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/companion.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constructor.kt")
|
||||
public void testConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/constructor.kt");
|
||||
@@ -5015,6 +5021,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("object.kt")
|
||||
public void testObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/object.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("receiverParameter.kt")
|
||||
public void testReceiverParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/receiverParameter.kt");
|
||||
@@ -5027,6 +5039,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("static.kt")
|
||||
public void testStatic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/static.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("staticTwoParameters.kt")
|
||||
public void testStaticTwoParameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/staticTwoParameters.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("threeParameters.kt")
|
||||
public void testThreeParameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/threeParameters.kt");
|
||||
|
||||
Reference in New Issue
Block a user