Reference --> lambda supports bound references now #KT-16292 Fixed

This commit is contained in:
Mikhail Glukhikh
2017-03-10 16:38:35 +03:00
parent f6734e74e1
commit 831467891c
14 changed files with 106 additions and 14 deletions
@@ -48,7 +48,7 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio
val parameterNamesAndTypes = targetDescriptor.valueParameters.map { it.name.asString() to it.type }
val receiverExpression = element.receiverExpression
val receiverType = receiverExpression?.let {
(context[DOUBLE_COLON_LHS, it] as? DoubleColonLHS.Type)?.type ?: return
(context[DOUBLE_COLON_LHS, it] as? DoubleColonLHS.Type)?.type
}
val receiverNameAndType = receiverType?.let { KotlinNameSuggester.suggestNamesByType(it, validator = {
name -> name !in parameterNamesAndTypes.map { it.first }
@@ -76,7 +76,9 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio
else -> receiverExpression?.let { it.text + "." } ?: ""
}
val lambdaExpression = if (valueArgumentParent != null && lambdaParameterNamesAndTypes.size == 1) {
val lambdaExpression = if (valueArgumentParent != null &&
lambdaParameterNamesAndTypes.size == 1 &&
receiverExpression?.text != "it") {
factory.createLambdaExpression(
parameters = "",
body = when {
@@ -117,13 +119,5 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio
}
}
override fun isApplicableTo(element: KtCallableReferenceExpression): Boolean {
val context = element.analyze(BodyResolveMode.PARTIAL)
val receiverExpression = element.receiverExpression
if (receiverExpression != null) {
val lhs = context[DOUBLE_COLON_LHS, receiverExpression]
if (lhs is DoubleColonLHS.Expression) return false
}
return true
}
override fun isApplicableTo(element: KtCallableReferenceExpression) = true
}
@@ -1,5 +1,5 @@
// IS_APPLICABLE: false
// IS_APPLICABLE: true
val x = 1
// Not supported yet
val y = <caret>x::hashCode
@@ -0,0 +1,5 @@
// IS_APPLICABLE: true
val x = 1
val y = { x.hashCode() }
@@ -0,0 +1,9 @@
// WITH_RUNTIME
val list = listOf(1, 2, 3).map(<caret>Utils.Companion::foo)
class Utils {
companion object {
fun foo(x: Int) = x
}
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
val list = listOf(1, 2, 3).map { Utils.foo(it) }
class Utils {
companion object {
fun foo(x: Int) = x
}
}
@@ -0,0 +1,9 @@
// IS_APPLICABLE: true
// WITH_RUNTIME
fun foo() {
listOf(1).forEach { (-it).let(<caret>it::bar) }
}
fun Int.bar(arg: Int) {
}
@@ -0,0 +1,9 @@
// IS_APPLICABLE: true
// WITH_RUNTIME
fun foo() {
listOf(1).forEach { (-it).let { arg -> it.bar(arg) } }
}
fun Int.bar(arg: Int) {
}
@@ -0,0 +1,4 @@
class Owner(val z: Int) {
fun foo(y: Int) = y + z
val x = <caret>this::foo
}
@@ -0,0 +1,4 @@
class Owner(val z: Int) {
fun foo(y: Int) = y + z
val x = { y: Int -> this.foo(y) }
}
@@ -0,0 +1,9 @@
// IS_APPLICABLE: true
// WITH_RUNTIME
fun foo() {
listOf(1).forEach { run(<caret>it::bar) }
}
fun Int.bar() {
}
@@ -0,0 +1,9 @@
// IS_APPLICABLE: true
// WITH_RUNTIME
fun foo() {
listOf(1).forEach { run { it.bar() } }
}
fun Int.bar() {
}
@@ -1,4 +1,4 @@
// IS_APPLICABLE: false
// IS_APPLICABLE: true
// WITH_RUNTIME
val list = listOf(1, 2, 3).map(<caret>Utils::foo)
@@ -0,0 +1,7 @@
// IS_APPLICABLE: true
// WITH_RUNTIME
val list = listOf(1, 2, 3).map { Utils.foo(it) }
object Utils {
fun foo(x: Int) = x
}
@@ -5336,6 +5336,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
doTest(fileName);
}
@TestMetadata("companionNoImport.kt")
public void testCompanionNoImport() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt");
doTest(fileName);
}
@TestMetadata("constructor.kt")
public void testConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/constructor.kt");
@@ -5372,18 +5378,36 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
doTest(fileName);
}
@TestMetadata("itClash.kt")
public void testItClash() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/itClash.kt");
doTest(fileName);
}
@TestMetadata("length.kt")
public void testLength() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/length.kt");
doTest(fileName);
}
@TestMetadata("member.kt")
public void testMember() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/member.kt");
doTest(fileName);
}
@TestMetadata("name.kt")
public void testName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/name.kt");
doTest(fileName);
}
@TestMetadata("nestedLambdaWithReceiver.kt")
public void testNestedLambdaWithReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt");
doTest(fileName);
}
@TestMetadata("nullable.kt")
public void testNullable() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertReferenceToLambda/nullable.kt");