From 24763937541a5085093ae5426a465891714e2ee3 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 2 Nov 2015 14:58:16 +0300 Subject: [PATCH] Change Signature: Do not move lambda out of parentheses if it neither wasn't out before nor corresponds to the last parameter after the refactoring #KT-9763 Fixed --- .../usages/JetFunctionCallUsage.java | 33 ++++++++++++++----- .../DefaultAfterLambdaAfter.kt | 5 +++ .../DefaultAfterLambdaBefore.kt | 5 +++ .../changeSignature/JetChangeSignatureTest.kt | 2 ++ 4 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 idea/testData/refactoring/changeSignature/DefaultAfterLambdaAfter.kt create mode 100644 idea/testData/refactoring/changeSignature/DefaultAfterLambdaBefore.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetFunctionCallUsage.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetFunctionCallUsage.java index 0a4e81865c8..acb677b5542 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetFunctionCallUsage.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetFunctionCallUsage.java @@ -24,6 +24,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.util.containers.ContainerUtil; import gnu.trove.TIntArrayList; import gnu.trove.TIntProcedure; +import kotlin.ArraysKt; import kotlin.CollectionsKt; import kotlin.Pair; import kotlin.Unit; @@ -370,7 +371,7 @@ public class JetFunctionCallUsage extends JetUsageInfo { parametersBuilder.append(')'); KtValueArgumentList newArgumentList = KtPsiFactoryKt.KtPsiFactory(getProject()).createCallArguments(parametersBuilder.toString()); - Map argumentMap = getParamIndexToArgumentMap(changeInfo, oldArguments); + Map argumentMap = getParamIndexToArgumentMap(changeInfo, oldArguments); JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo(); JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver(); @@ -410,9 +411,12 @@ public class JetFunctionCallUsage extends JetUsageInfo { KtSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null; changeArgumentName(argumentNameExpression, parameterInfo); //noinspection ConstantConditions - newArgument.replace(oldArgument instanceof KtFunctionLiteralArgument - ? psiFactory.createArgument(oldArgument.getArgumentExpression(), null, false) - : oldArgument.asElement()); + ValueArgument argumentReplacement = (ValueArgument) newArgument.replace( + oldArgument instanceof KtFunctionLiteralArgument + ? psiFactory.createArgument(oldArgument.getArgumentExpression(), null, false) + : oldArgument.asElement() + ); + argumentMap.put(parameterInfo.getOldIndex(), argumentReplacement); } // TODO: process default arguments in the middle else if (parameterInfo.getDefaultValueForCall() == null) { @@ -429,14 +433,25 @@ public class JetFunctionCallUsage extends JetUsageInfo { } List lambdaArguments = element.getFunctionLiteralArguments(); - if (!lambdaArguments.isEmpty()) { + boolean hasLambdaArgumentsBefore = !lambdaArguments.isEmpty(); + if (hasLambdaArgumentsBefore) { element.deleteChildRange(CollectionsKt.first(lambdaArguments), CollectionsKt.last(lambdaArguments)); } - //TODO: this is not correct! KtValueArgument lastArgument = CollectionsKt.lastOrNull(newArgumentList.getArguments()); + KtFunctionLiteralExpression lastLambdaExpr = + lastArgument != null ? KtFunctionLiteralArgumentKt.unpackFunctionLiteral(lastArgument.getArgumentExpression()) : null; + JetParameterInfo lastNewParam = ArraysKt.lastOrNull(changeInfo.getNewParameters()); boolean hasTrailingLambdaInArgumentListAfter = - lastArgument != null && KtFunctionLiteralArgumentKt.unpackFunctionLiteral(lastArgument.getArgumentExpression()) != null; + lastLambdaExpr != null && lastNewParam != null && argumentMap.get(lastNewParam.getOldIndex()) == lastArgument; + boolean newLambdaWithDefaultValueWasAdded = + lastNewParam != null + && lastNewParam.isNewParameter() + && lastNewParam.getDefaultValueForCall() instanceof KtFunctionLiteralExpression + && lastArgument != null + && !lastArgument.isNamed(); + boolean shouldMoveLambdaOut = + hasTrailingLambdaInArgumentListAfter && hasLambdaArgumentsBefore || newLambdaWithDefaultValueWasAdded; arguments = (KtValueArgumentList) arguments.replace(newArgumentList); @@ -477,7 +492,7 @@ public class JetFunctionCallUsage extends JetUsageInfo { newElement = (KtElement) elementToReplace.replace(replacingElement); } - if (hasTrailingLambdaInArgumentListAfter) { + if (shouldMoveLambdaOut) { KtCallExpression newCallExpression = (KtCallExpression) (newElement instanceof KtQualifiedExpression ? ((KtQualifiedExpression) newElement).getSelectorExpression() @@ -531,7 +546,7 @@ public class JetFunctionCallUsage extends JetUsageInfo { return null; } - private static Map getParamIndexToArgumentMap(JetChangeInfo changeInfo, List oldArguments) { + private static Map getParamIndexToArgumentMap(JetChangeInfo changeInfo, List oldArguments) { Map argumentMap = new HashMap(); for (int i = 0; i < oldArguments.size(); i++) { diff --git a/idea/testData/refactoring/changeSignature/DefaultAfterLambdaAfter.kt b/idea/testData/refactoring/changeSignature/DefaultAfterLambdaAfter.kt new file mode 100644 index 00000000000..bd7b2e5d762 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/DefaultAfterLambdaAfter.kt @@ -0,0 +1,5 @@ +fun foo(p2: Int, p1: Int, filter: (Int) -> Boolean, p3: Int = 0){} + +fun bar() { + foo(2, 1, { true }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/DefaultAfterLambdaBefore.kt b/idea/testData/refactoring/changeSignature/DefaultAfterLambdaBefore.kt new file mode 100644 index 00000000000..f446e58c4f2 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/DefaultAfterLambdaBefore.kt @@ -0,0 +1,5 @@ +fun foo(p1: Int, p2: Int, filter: (Int) -> Boolean, p3: Int = 0){} + +fun bar() { + foo(1, 2, { true }) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureTest.kt index 8efb4040eda..2b72ede6199 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureTest.kt @@ -833,4 +833,6 @@ class JetChangeSignatureTest : KotlinCodeInsightTestCase() { fun testJvmOverloadedRemoveNonDefault3() = doTest { removeParameter(getNewParametersCount() - 1) } fun testJvmOverloadedConstructorSwapParams() = doTest { swapParameters(1, 2) } + + fun testDefaultAfterLambda() = doTest { swapParameters(0, 1) } }