diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeInliner.kt b/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeInliner.kt index 50487edb9ab..f5c919b6737 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeInliner.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeInliner.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.codeInliner import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement +import com.intellij.refactoring.rename.RenameProcessor import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor @@ -26,11 +27,9 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference import org.jetbrains.kotlin.idea.core.* import org.jetbrains.kotlin.idea.intentions.RemoveExplicitTypeArgumentsIntention -import org.jetbrains.kotlin.idea.util.CommentSaver -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.idea.util.ImportInsertHelper -import org.jetbrains.kotlin.idea.util.getResolutionScope +import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext @@ -40,6 +39,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.addIfNotNull @@ -95,6 +95,9 @@ class CodeInliner( processTypeParameterUsages() + + val lexicalScope = callElement.parent.getResolutionScope(bindingContext) + if (elementToBeReplaced is KtSafeQualifiedExpression) { wrapCodeForSafeCall(receiver!!, receiverType, elementToBeReplaced) } @@ -127,7 +130,7 @@ class CodeInliner( } return replacementPerformer.doIt(postProcessing = { range -> - val newRange = postProcessInsertedCode(range) + val newRange = postProcessInsertedCode(range, lexicalScope) if (!newRange.isEmpty) { commentSaver.restore(newRange) } @@ -135,6 +138,24 @@ class CodeInliner( }) } + private fun renameDuplicates(declarations: List, + lexicalScope: LexicalScope) { + + fun String.hasConflicts() = lexicalScope.getAllAccessibleVariables(Name.identifier(this)).any { + !it.isExtension && it.isVisible(lexicalScope.ownerDescriptor) + } + + val validator = CollectingNameValidator { !it.hasConflicts() } + for (declaration in declarations) { + val oldName = declaration.name + if (oldName != null && oldName.hasConflicts()) { + val newName = KotlinNameSuggester.suggestNameByName(oldName, validator) + val renameProcessor = RenameProcessor(project, declaration, newName, false, false) + renameProcessor.run() + } + } + } + private fun processValueParameterUsages(): Collection { val introduceValuesForParameters = ArrayList() @@ -356,10 +377,14 @@ class CodeInliner( } } - private fun postProcessInsertedCode(range: PsiChildRange): PsiChildRange { + private fun postProcessInsertedCode(range: PsiChildRange, lexicalScope: LexicalScope?): PsiChildRange { val elements = range.filterIsInstance().toList() if (elements.isEmpty()) return PsiChildRange.EMPTY + lexicalScope?.let { + renameDuplicates(elements.dropLast(1).filterIsInstance(), it) + } + elements.forEach { introduceNamedArguments(it) diff --git a/idea/testData/refactoring/inline/function/expressionBody/MultipleInExpression.kt.after b/idea/testData/refactoring/inline/function/expressionBody/MultipleInExpression.kt.after index 4903702ed2a..39fb8652d28 100644 --- a/idea/testData/refactoring/inline/function/expressionBody/MultipleInExpression.kt.after +++ b/idea/testData/refactoring/inline/function/expressionBody/MultipleInExpression.kt.after @@ -1,8 +1,8 @@ class Point(val x: Double, val y: Double) { // After sqr inlining, only first usage of sqr is replaced fun distance(other: Point): Double { - val x = x - other.x + val x1 = x - other.x // See KT-17022 - return Math.sqrt(x * x + sqr(y - other.y)) + return Math.sqrt(x1 * x1 + sqr(y - other.y)) } } \ No newline at end of file diff --git a/idea/testData/refactoring/inline/function/returnAtEnd/PrivateMember.kt.after b/idea/testData/refactoring/inline/function/returnAtEnd/PrivateMember.kt.after index fda45fc39fa..c257b899cf3 100644 --- a/idea/testData/refactoring/inline/function/returnAtEnd/PrivateMember.kt.after +++ b/idea/testData/refactoring/inline/function/returnAtEnd/PrivateMember.kt.after @@ -1,8 +1,7 @@ class My { fun run() { - // foo1 should be here - val foo = 1 + 2 - val foo = foo + val foo1 = 1 + 2 + val foo = foo1 System.out.println(foo) } diff --git a/idea/testData/refactoring/inline/function/returnAtEnd/PublicMember.kt.after b/idea/testData/refactoring/inline/function/returnAtEnd/PublicMember.kt.after index fda45fc39fa..c257b899cf3 100644 --- a/idea/testData/refactoring/inline/function/returnAtEnd/PublicMember.kt.after +++ b/idea/testData/refactoring/inline/function/returnAtEnd/PublicMember.kt.after @@ -1,8 +1,7 @@ class My { fun run() { - // foo1 should be here - val foo = 1 + 2 - val foo = foo + val foo1 = 1 + 2 + val foo = foo1 System.out.println(foo) }