Lambda to reference: correct handling of named arguments using resolved call #KT-14550 Fixed

This commit is contained in:
Mikhail Glukhikh
2016-10-27 13:01:24 +03:00
parent 7d242c5c77
commit 7b316f72dc
5 changed files with 30 additions and 3 deletions
@@ -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
@@ -0,0 +1,3 @@
fun foo(x: Int, y: Int) = x + y
val x = { y: Int, x: Int <caret>-> foo(y = x, x = y) }
@@ -0,0 +1,3 @@
fun foo(x: Int, y: Int) = x + y
val x = ::foo
@@ -0,0 +1,5 @@
// IS_APPLICABLE: false
fun foo(x: Int, y: Int) = x + y
val x = { x: Int, y: Int <caret>-> foo(y = x, x = y) }
@@ -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");