From 831467891c398031f9cd7b8bf79673b3f8d6b6df Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 10 Mar 2017 16:38:35 +0300 Subject: [PATCH] Reference --> lambda supports bound references now #KT-16292 Fixed --- .../ConvertReferenceToLambdaIntention.kt | 16 ++++--------- .../boundReference.kt | 4 ++-- .../boundReference.kt.after | 5 ++++ .../companionNoImport.kt | 9 +++++++ .../companionNoImport.kt.after | 9 +++++++ .../convertReferenceToLambda/itClash.kt | 9 +++++++ .../convertReferenceToLambda/itClash.kt.after | 9 +++++++ .../convertReferenceToLambda/member.kt | 4 ++++ .../convertReferenceToLambda/member.kt.after | 4 ++++ .../nestedLambdaWithReceiver.kt | 9 +++++++ .../nestedLambdaWithReceiver.kt.after | 9 +++++++ .../convertReferenceToLambda/object.kt | 2 +- .../convertReferenceToLambda/object.kt.after | 7 ++++++ .../intentions/IntentionTestGenerated.java | 24 +++++++++++++++++++ 14 files changed, 106 insertions(+), 14 deletions(-) create mode 100644 idea/testData/intentions/convertReferenceToLambda/boundReference.kt.after create mode 100644 idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt create mode 100644 idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt.after create mode 100644 idea/testData/intentions/convertReferenceToLambda/itClash.kt create mode 100644 idea/testData/intentions/convertReferenceToLambda/itClash.kt.after create mode 100644 idea/testData/intentions/convertReferenceToLambda/member.kt create mode 100644 idea/testData/intentions/convertReferenceToLambda/member.kt.after create mode 100644 idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt create mode 100644 idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt.after create mode 100644 idea/testData/intentions/convertReferenceToLambda/object.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReferenceToLambdaIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReferenceToLambdaIntention.kt index 7c104638429..3d45096bbdc 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReferenceToLambdaIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReferenceToLambdaIntention.kt @@ -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 } \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/boundReference.kt b/idea/testData/intentions/convertReferenceToLambda/boundReference.kt index e3aa0cdcbcd..f6e47177801 100644 --- a/idea/testData/intentions/convertReferenceToLambda/boundReference.kt +++ b/idea/testData/intentions/convertReferenceToLambda/boundReference.kt @@ -1,5 +1,5 @@ -// IS_APPLICABLE: false +// IS_APPLICABLE: true val x = 1 -// Not supported yet + val y = x::hashCode \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/boundReference.kt.after b/idea/testData/intentions/convertReferenceToLambda/boundReference.kt.after new file mode 100644 index 00000000000..54785b2e990 --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/boundReference.kt.after @@ -0,0 +1,5 @@ +// IS_APPLICABLE: true + +val x = 1 + +val y = { x.hashCode() } \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt b/idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt new file mode 100644 index 00000000000..00c4cef1dab --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt @@ -0,0 +1,9 @@ +// WITH_RUNTIME + +val list = listOf(1, 2, 3).map(Utils.Companion::foo) + +class Utils { + companion object { + fun foo(x: Int) = x + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt.after b/idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt.after new file mode 100644 index 00000000000..b9cf9443b69 --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/companionNoImport.kt.after @@ -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 + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/itClash.kt b/idea/testData/intentions/convertReferenceToLambda/itClash.kt new file mode 100644 index 00000000000..0aec80a5197 --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/itClash.kt @@ -0,0 +1,9 @@ +// IS_APPLICABLE: true +// WITH_RUNTIME + +fun foo() { + listOf(1).forEach { (-it).let(it::bar) } +} + +fun Int.bar(arg: Int) { +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/itClash.kt.after b/idea/testData/intentions/convertReferenceToLambda/itClash.kt.after new file mode 100644 index 00000000000..0fac9bec33a --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/itClash.kt.after @@ -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) { +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/member.kt b/idea/testData/intentions/convertReferenceToLambda/member.kt new file mode 100644 index 00000000000..37c79115f68 --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/member.kt @@ -0,0 +1,4 @@ +class Owner(val z: Int) { + fun foo(y: Int) = y + z + val x = this::foo +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/member.kt.after b/idea/testData/intentions/convertReferenceToLambda/member.kt.after new file mode 100644 index 00000000000..0c28447fa0c --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/member.kt.after @@ -0,0 +1,4 @@ +class Owner(val z: Int) { + fun foo(y: Int) = y + z + val x = { y: Int -> this.foo(y) } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt b/idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt new file mode 100644 index 00000000000..dff8ce2e25f --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt @@ -0,0 +1,9 @@ +// IS_APPLICABLE: true +// WITH_RUNTIME + +fun foo() { + listOf(1).forEach { run(it::bar) } +} + +fun Int.bar() { +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt.after b/idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt.after new file mode 100644 index 00000000000..6ee5b5ed169 --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/nestedLambdaWithReceiver.kt.after @@ -0,0 +1,9 @@ +// IS_APPLICABLE: true +// WITH_RUNTIME + +fun foo() { + listOf(1).forEach { run { it.bar() } } +} + +fun Int.bar() { +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReferenceToLambda/object.kt b/idea/testData/intentions/convertReferenceToLambda/object.kt index 3e21ca06219..9bfb97f5953 100644 --- a/idea/testData/intentions/convertReferenceToLambda/object.kt +++ b/idea/testData/intentions/convertReferenceToLambda/object.kt @@ -1,4 +1,4 @@ -// IS_APPLICABLE: false +// IS_APPLICABLE: true // WITH_RUNTIME val list = listOf(1, 2, 3).map(Utils::foo) diff --git a/idea/testData/intentions/convertReferenceToLambda/object.kt.after b/idea/testData/intentions/convertReferenceToLambda/object.kt.after new file mode 100644 index 00000000000..318b35f030b --- /dev/null +++ b/idea/testData/intentions/convertReferenceToLambda/object.kt.after @@ -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 +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 149322dfd7a..d7b472ccfc6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -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");