From 0badf4c448a15ebe87008ee6a1b4c05bf06b6e4c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 28 Nov 2023 21:24:05 +0100 Subject: [PATCH] [kotlin] rename: ensure replace takes an element of a corresponding type ^KTIJ-24219 fixed add check to test that psi structure after modification is the same to the psi structure from text: this guarantees that psi is replaced consistently and no reparse is needed to produce correct psi GitOrigin-RevId: f97ff4ec92401e94a1941ad81f1a7f4d0093af29 --- .../refactoring/rename/AbstractRenameTest.kt | 2 ++ .../rename/RenameTestGenerated.java | 5 ++++ .../rename/renamePlus1/after/plus.kt | 7 ++++++ .../rename/renamePlus1/before/plus.kt | 7 ++++++ .../refactoring/rename/renamePlus1/plus1.test | 8 +++++++ .../rename/KtReferenceMutateServiceBase.kt | 23 +++++++++---------- .../rename/FirRenameTestGenerated.java | 5 ++++ 7 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/after/plus.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/before/plus.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/plus1.test diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt index 8193c6e91ef3..f7e05b21371b 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt @@ -30,6 +30,7 @@ import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.PlatformTestUtil +import com.intellij.testFramework.PsiTestUtil import com.intellij.testFramework.UsefulTestCase import com.intellij.testFramework.fixtures.CodeInsightTestUtil import org.jetbrains.kotlin.asJava.finder.KtLightPackage @@ -365,6 +366,7 @@ abstract class AbstractRenameTest : KotlinLightCodeInsightFixtureTestCase() { RenamePsiElementProcessor.forElement(psiElement).substituteElementToRename(psiElement, null) runRenameProcessor(context.project, newName, substitution, renameParamsObject, true, true) + PsiTestUtil.checkFileStructure(ktFile) } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java index 02cef0f5d0a8..e65dff588627 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java @@ -1263,6 +1263,11 @@ public class RenameTestGenerated extends AbstractRenameTest { runTest("testData/refactoring/rename/renamePackageWithQuotation/renamePackageWithQuotation.test"); } + @TestMetadata("renamePlus1/plus1.test") + public void testRenamePlus1_Plus1() throws Exception { + runTest("testData/refactoring/rename/renamePlus1/plus1.test"); + } + @TestMetadata("renamePlusAssign/plusAssign.test") public void testRenamePlusAssign_PlusAssign() throws Exception { runTest("testData/refactoring/rename/renamePlusAssign/plusAssign.test"); diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/after/plus.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/after/plus.kt new file mode 100644 index 000000000000..179922fcfb8f --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/after/plus.kt @@ -0,0 +1,7 @@ +data class Point(val x:Int, val y: Int) { + fun foo(other: Point): Point { + return Point(x + other.x, y + other.y) + } +} + +fun test(p: Point) = p.foo(p) \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/before/plus.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/before/plus.kt new file mode 100644 index 000000000000..e57488c5a0f3 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/before/plus.kt @@ -0,0 +1,7 @@ +data class Point(val x:Int, val y: Int) { + operator fun plus(other: Point): Point { + return Point(x + other.x, y + other.y) + } +} + +fun test(p: Point) = p + p \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/plus1.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/plus1.test new file mode 100644 index 000000000000..fe365ce10be1 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renamePlus1/plus1.test @@ -0,0 +1,8 @@ +{ + "type": "KOTLIN_FUNCTION", + "classId": "/Point", + "oldName": "plus", + "newName": "foo", + "mainFile": "plus.kt", + "enabledInK2": true +} \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KtReferenceMutateServiceBase.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KtReferenceMutateServiceBase.kt index 1e50790c799d..2507555cae65 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KtReferenceMutateServiceBase.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KtReferenceMutateServiceBase.kt @@ -209,22 +209,21 @@ abstract class KtReferenceMutateServiceBase : KtReferenceMutateService { } } - val psiFactory = KtPsiFactory(expression) + val psiFactory = KtPsiFactory(expression.project) + val nameElement = expression.getReferencedNameElement() + val elementType = nameElement.node.elementType + val opExpression = if (elementType is KtToken && OperatorConventions.getNameForOperationSymbol(elementType) != null) { + expression.parent as? KtOperationExpression + } else null val element = expression.project.extensionArea.getExtensionPoint(SimpleNameReferenceExtension.EP_NAME).extensions .asSequence() .map { it.handleElementRename(this, psiFactory, newElementName) } - .firstOrNull { it != null } ?: psiFactory.createNameIdentifier(newElementName.quoteIfNeeded()) + .firstOrNull { it != null } ?: if (opExpression != null) psiFactory.createSimpleName(newElementName.quoteIfNeeded()) else psiFactory.createNameIdentifier(newElementName.quoteIfNeeded()) - val nameElement = expression.getReferencedNameElement() - - val elementType = nameElement.node.elementType - if (elementType is KtToken && OperatorConventions.getNameForOperationSymbol(elementType) != null) { - val opExpression = expression.parent as? KtOperationExpression - if (opExpression != null) { - val (newExpression, newNameElement) = convertOperatorToFunctionCall(opExpression) - newNameElement.replace(element) - return newExpression - } + if (opExpression != null) { + val (newExpression, newNameElement) = convertOperatorToFunctionCall(opExpression) + newNameElement.replace(psiFactory.createSimpleName(newElementName.quoteIfNeeded())) + return newExpression } if (element.node.elementType == KtTokens.IDENTIFIER) { diff --git a/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/FirRenameTestGenerated.java b/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/FirRenameTestGenerated.java index bdeb25bca20f..ddd2533bc1d5 100644 --- a/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/FirRenameTestGenerated.java +++ b/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/FirRenameTestGenerated.java @@ -1263,6 +1263,11 @@ public class FirRenameTestGenerated extends AbstractFirRenameTest { runTest("../../idea/tests/testData/refactoring/rename/renamePackageWithQuotation/renamePackageWithQuotation.test"); } + @TestMetadata("renamePlus1/plus1.test") + public void testRenamePlus1_Plus1() throws Exception { + runTest("../../idea/tests/testData/refactoring/rename/renamePlus1/plus1.test"); + } + @TestMetadata("renamePlusAssign/plusAssign.test") public void testRenamePlusAssign_PlusAssign() throws Exception { runTest("../../idea/tests/testData/refactoring/rename/renamePlusAssign/plusAssign.test");