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.BindingContext.REFERENCE_TARGET
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
|
||||||
|
|
||||||
class ConvertReferenceToLambdaInspection : IntentionBasedInspection<KtCallableReferenceExpression>(ConvertReferenceToLambdaIntention::class)
|
class ConvertReferenceToLambdaInspection : IntentionBasedInspection<KtCallableReferenceExpression>(ConvertReferenceToLambdaIntention::class)
|
||||||
|
|
||||||
@@ -51,23 +50,31 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio
|
|||||||
val receiverNameAndType = receiverType?.let { KotlinNameSuggester.suggestNamesByType(it, validator = {
|
val receiverNameAndType = receiverType?.let { KotlinNameSuggester.suggestNamesByType(it, validator = {
|
||||||
name -> name !in parameterNamesAndTypes.map { it.first }
|
name -> name !in parameterNamesAndTypes.map { it.first }
|
||||||
}, defaultName = "receiver").first() to it }
|
}, defaultName = "receiver").first() to it }
|
||||||
|
val acceptsReceiverAsParameter = receiverNameAndType != null &&
|
||||||
|
(targetDescriptor.dispatchReceiverParameter != null ||
|
||||||
|
targetDescriptor.extensionReceiverParameter != null)
|
||||||
|
|
||||||
val referenceParent = element.parent
|
val referenceParent = element.parent
|
||||||
val insideCall = referenceParent is KtValueArgument
|
val insideCall = referenceParent is KtValueArgument
|
||||||
|
|
||||||
val factory = KtPsiFactory(element)
|
val factory = KtPsiFactory(element)
|
||||||
val targetName = reference.text
|
val targetName = reference.text
|
||||||
val lambdaParameterNamesAndTypes = receiverNameAndType.singletonOrEmptyList() + parameterNamesAndTypes
|
val lambdaParameterNamesAndTypes =
|
||||||
val receiverPrefix = receiverNameAndType?.let { it.first + "." } ?: ""
|
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) {
|
val lambdaExpression = if (insideCall && lambdaParameterNamesAndTypes.size == 1) {
|
||||||
factory.createLambdaExpression(
|
factory.createLambdaExpression(
|
||||||
parameters = "",
|
parameters = "",
|
||||||
body = when {
|
body = when {
|
||||||
receiverNameAndType != null ->
|
acceptsReceiverAsParameter ->
|
||||||
if (targetDescriptor is PropertyDescriptor) "it.$targetName"
|
if (targetDescriptor is PropertyDescriptor) "it.$targetName"
|
||||||
else "it.$targetName()"
|
else "it.$targetName()"
|
||||||
else ->
|
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);
|
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")
|
@TestMetadata("constructor.kt")
|
||||||
public void testConstructor() throws Exception {
|
public void testConstructor() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/constructor.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/constructor.kt");
|
||||||
@@ -5015,6 +5021,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("receiverParameter.kt")
|
||||||
public void testReceiverParameter() throws Exception {
|
public void testReceiverParameter() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/receiverParameter.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/receiverParameter.kt");
|
||||||
@@ -5027,6 +5039,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("threeParameters.kt")
|
||||||
public void testThreeParameters() throws Exception {
|
public void testThreeParameters() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/threeParameters.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/threeParameters.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user