From 45234c97847dc60907a31296e3519cae641161d1 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Thu, 25 Jun 2020 17:13:29 +0700 Subject: [PATCH] Inline refactoring: fix case with introduction of variable to return #KT-39818 Fixed --- .../kotlin/idea/codeInliner/CodeInliner.kt | 6 ++++-- .../idea/codeInliner/MutableCodeToInline.kt | 8 +------- .../kotlin/idea/codeInliner/introduceValue.kt | 19 ++++--------------- .../idea/refactoring/inline/inlineUtils.kt | 2 +- .../refactoring/inline/function/Kt39818.kt | 10 ++++++++++ .../inline/function/Kt39818.kt.after | 8 ++++++++ .../inline/InlineTestGenerated.java | 5 +++++ 7 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 idea/testData/refactoring/inline/function/Kt39818.kt create mode 100644 idea/testData/refactoring/inline/function/Kt39818.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeInliner.kt b/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeInliner.kt index 1817b9da91f..9759eb744c7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeInliner.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeInliner.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -181,6 +181,7 @@ class CodeInliner( val usages = codeToInline.collectDescendantsOfType { it[CodeToInline.PARAMETER_USAGE_KEY] == parameterName } + usages.forEach { val usageArgument = it.parent as? KtValueArgument if (argument.isNamed) { @@ -189,7 +190,8 @@ class CodeInliner( if (argument.isDefaultValue) { usageArgument?.mark(DEFAULT_PARAMETER_VALUE_KEY) } - codeToInline.replaceExpression(it, argument.expression) + + codeToInline.replaceExpression(it, argument.expression.copied()) } //TODO: sometimes we need to add explicit type arguments here because we don't have expected type in the new context diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInliner/MutableCodeToInline.kt b/idea/src/org/jetbrains/kotlin/idea/codeInliner/MutableCodeToInline.kt index c93a07d7873..6d2cd4fdd13 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInliner/MutableCodeToInline.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInliner/MutableCodeToInline.kt @@ -72,13 +72,7 @@ internal class MutableCodeToInline( val expressions: Collection get() = statementsBefore + listOfNotNull(mainExpression) - operator fun contains(element: PsiElement): Boolean { - return expressions.any { it.isAncestor(element) } - } - - fun containsStrictlyInside(element: PsiElement): Boolean { - return expressions.any { it.isAncestor(element, strict = true) } - } + operator fun contains(element: PsiElement): Boolean = expressions.any { it.isAncestor(element) } } internal fun CodeToInline.toMutable(): MutableCodeToInline { diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInliner/introduceValue.kt b/idea/src/org/jetbrains/kotlin/idea/codeInliner/introduceValue.kt index d335f314d10..d2990137f3f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInliner/introduceValue.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInliner/introduceValue.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.idea.codeInliner @@ -57,7 +46,7 @@ internal fun MutableCodeToInline.introduceValue( nameSuggestion: String? = null, safeCall: Boolean = false ) { - assert(usages.all { this.containsStrictlyInside(it) }) + assert(usages.all { it in this }) val psiFactory = KtPsiFactory(value) @@ -68,7 +57,7 @@ internal fun MutableCodeToInline.introduceValue( for (usage in usages) { // there can be parenthesis around the expression which will become unnecessary val usageToReplace = (usage.parent as? KtParenthesizedExpression) ?: usage - usageToReplace.replace(nameInCode) + replaceExpression(usageToReplace, nameInCode) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/inlineUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/inlineUtils.kt index 1f5d19295ec..ea9c273af2a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/inlineUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/inlineUtils.kt @@ -166,7 +166,7 @@ internal fun buildCodeToInline( } return builder.prepareCodeToInline( - lastReturn?.returnedExpression, + lastReturn?.returnedExpression?.copied(), statements.dropLast(returnStatements.size), ::analyzeExpressionInContext, reformat = true ) } else { diff --git a/idea/testData/refactoring/inline/function/Kt39818.kt b/idea/testData/refactoring/inline/function/Kt39818.kt new file mode 100644 index 00000000000..e4e304c9d65 --- /dev/null +++ b/idea/testData/refactoring/inline/function/Kt39818.kt @@ -0,0 +1,10 @@ +fun downUnder(): Int = 4 +fun downParameter(p: Int): Int { + "first $p" + "second $p" + p + return p +} +fun callDown() { + val result = downParameter(downUnder()) +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/function/Kt39818.kt.after b/idea/testData/refactoring/inline/function/Kt39818.kt.after new file mode 100644 index 00000000000..cef2298637e --- /dev/null +++ b/idea/testData/refactoring/inline/function/Kt39818.kt.after @@ -0,0 +1,8 @@ +fun downUnder(): Int = 4 +fun callDown() { + val p = downUnder() + "first ${p}" + "second ${p}" + p + val result = p +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java index d6100a21c84..d9a81fde51e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java @@ -65,6 +65,11 @@ public class InlineTestGenerated extends AbstractInlineTest { runTest("idea/testData/refactoring/inline/function/Kt30131.kt"); } + @TestMetadata("Kt39818.kt") + public void testKt39818() throws Exception { + runTest("idea/testData/refactoring/inline/function/Kt39818.kt"); + } + @TestMetadata("LocalCapturing.kt") public void testLocalCapturing() throws Exception { runTest("idea/testData/refactoring/inline/function/LocalCapturing.kt");