From 7b316f72dc8b068a56fad4d1ec9c56d563d23c05 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 27 Oct 2016 13:01:24 +0300 Subject: [PATCH] Lambda to reference: correct handling of named arguments using resolved call #KT-14550 Fixed --- .../intentions/ConvertLambdaToReferenceIntention.kt | 10 +++++++--- .../convertLambdaToReference/goodNamedOrder.kt | 3 +++ .../convertLambdaToReference/goodNamedOrder.kt.after | 3 +++ .../convertLambdaToReference/wrongNamedOrder.kt | 5 +++++ .../idea/intentions/IntentionTestGenerated.java | 12 ++++++++++++ 5 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt create mode 100644 idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt.after create mode 100644 idea/testData/intentions/convertLambdaToReference/wrongNamedOrder.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt index 380514307ed..8171bb3fe51 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext.FUNCTION import org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.types.isDynamic @@ -130,10 +131,13 @@ class ConvertLambdaToReferenceIntention : SelfTargetingOffsetIndependentIntentio // Same lambda / references function parameter order if (callableExpression is KtCallExpression) { if (lambdaValueParameters.size < receiverShift + callableExpression.valueArguments.size) return false - callableExpression.valueArguments.forEachIndexed { i, argument -> - val argumentExpression = argument.getArgumentExpression() as? KtNameReferenceExpression ?: return false + val resolvedCall = callableExpression.getResolvedCall(context) ?: return false + resolvedCall.valueArguments.entries.forEach { (valueParameter, resolvedArgument) -> + val argumentExpression = + resolvedArgument.arguments.singleOrNull()?.getArgumentExpression() as? KtNameReferenceExpression + ?: return false val argumentTarget = context[REFERENCE_TARGET, argumentExpression] as? ValueParameterDescriptor ?: return false - if (argumentTarget != lambdaValueParameters[i + receiverShift]) return false + if (argumentTarget != lambdaValueParameters[valueParameter.index + receiverShift]) return false } } return true diff --git a/idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt b/idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt new file mode 100644 index 00000000000..8f74159bd42 --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt @@ -0,0 +1,3 @@ +fun foo(x: Int, y: Int) = x + y + +val x = { y: Int, x: Int -> foo(y = x, x = y) } \ No newline at end of file diff --git a/idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt.after b/idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt.after new file mode 100644 index 00000000000..931c52bba96 --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt.after @@ -0,0 +1,3 @@ +fun foo(x: Int, y: Int) = x + y + +val x = ::foo \ No newline at end of file diff --git a/idea/testData/intentions/convertLambdaToReference/wrongNamedOrder.kt b/idea/testData/intentions/convertLambdaToReference/wrongNamedOrder.kt new file mode 100644 index 00000000000..38ee7e7a099 --- /dev/null +++ b/idea/testData/intentions/convertLambdaToReference/wrongNamedOrder.kt @@ -0,0 +1,5 @@ +// IS_APPLICABLE: false + +fun foo(x: Int, y: Int) = x + y + +val x = { x: Int, y: Int -> foo(y = x, x = y) } \ 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 04cc4284843..0d1b9002671 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -4087,6 +4087,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("goodNamedOrder.kt") + public void testGoodNamedOrder() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertLambdaToReference/goodNamedOrder.kt"); + doTest(fileName); + } + @TestMetadata("inner.kt") public void testInner() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertLambdaToReference/inner.kt"); @@ -4213,6 +4219,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("wrongNamedOrder.kt") + public void testWrongNamedOrder() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertLambdaToReference/wrongNamedOrder.kt"); + doTest(fileName); + } + @TestMetadata("wrongParameterNumber.kt") public void testWrongParameterNumber() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertLambdaToReference/wrongParameterNumber.kt");