From eea9113d1c9a361ecd9122d3b8e087004107fa93 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 31 May 2018 15:39:43 +0300 Subject: [PATCH] Introduce Type Alias: Fix replacement of references to nested classes #KT-15159 Fixed --- .../introduceTypeAliasImpl.kt | 21 ++++++++++++++---- .../introduceTypeAlias/deeplyNestedClass.kt | 19 ++++++++++++++++ .../deeplyNestedClass.kt.after | 22 +++++++++++++++++++ .../introduceTypeAlias/nestedClass.kt | 17 ++++++++++++++ .../introduceTypeAlias/nestedClass.kt.after | 20 +++++++++++++++++ .../introduce/ExtractionTestGenerated.java | 10 +++++++++ 6 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt create mode 100644 idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt.after create mode 100644 idea/testData/refactoring/introduceTypeAlias/nestedClass.kt create mode 100644 idea/testData/refactoring/introduceTypeAlias/nestedClass.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceTypeAlias/introduceTypeAliasImpl.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceTypeAlias/introduceTypeAliasImpl.kt index d70f249239c..3b11ce6bb8c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceTypeAlias/introduceTypeAliasImpl.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceTypeAlias/introduceTypeAliasImpl.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.core.CollectingNameValidator import org.jetbrains.kotlin.idea.core.KotlinNameSuggester import org.jetbrains.kotlin.idea.core.compareDescriptors +import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.refactoring.introduce.insertDeclaration import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange @@ -164,23 +165,35 @@ fun findDuplicates(typeAlias: KtTypeAlias): Map Unit> { val psiFactory = KtPsiFactory(typeAlias) + fun replaceTypeElement(occurrence: KtTypeElement, typeArgumentsText: String) { + occurrence.replace(psiFactory.createType("$aliasName$typeArgumentsText").typeElement!!) + } + fun replaceOccurrence(occurrence: PsiElement, arguments: List) { val typeArgumentsText = if (arguments.isNotEmpty()) "<${arguments.joinToString { it.text }}>" else "" when (occurrence) { is KtTypeElement -> { - occurrence.replace(psiFactory.createType("$aliasName$typeArgumentsText").typeElement!!) + replaceTypeElement(occurrence, typeArgumentsText) + } + + is KtSuperTypeCallEntry -> { + occurrence.calleeExpression.typeReference?.typeElement?.let { replaceTypeElement(it, typeArgumentsText) } } is KtCallElement -> { - val typeArgumentList = occurrence.typeArgumentList + val qualifiedExpression = occurrence.parent as? KtQualifiedExpression + val callExpression = if (qualifiedExpression != null && qualifiedExpression.selectorExpression == occurrence) { + qualifiedExpression.replaced(occurrence) + } else occurrence + val typeArgumentList = callExpression.typeArgumentList if (arguments.isNotEmpty()) { val newTypeArgumentList = psiFactory.createTypeArguments(typeArgumentsText) - typeArgumentList?.replace(newTypeArgumentList) ?: occurrence.addAfter(newTypeArgumentList, occurrence) + typeArgumentList?.replace(newTypeArgumentList) ?: callExpression.addAfter(newTypeArgumentList, callExpression.calleeExpression) } else { typeArgumentList?.delete() } - occurrence.calleeExpression?.replace(psiFactory.createExpression(aliasName)) + callExpression.calleeExpression?.replace(psiFactory.createExpression(aliasName)) } is KtExpression -> occurrence.replace(psiFactory.createExpression(aliasName)) diff --git a/idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt b/idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt new file mode 100644 index 00000000000..6d1612be0ea --- /dev/null +++ b/idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt @@ -0,0 +1,19 @@ +// NAME: Aliased +open class Outer{ + open class Middle { + open class Nested + } +} + +fun f2(){ + val o3 = Outer.Middle.Nested() // (1) +} + +val g3: Outer.Middle.Nested = Outer.Middle.Nested() //(2) + +fun f3(p: Outer.Middle.Nested): Outer.Middle.Nested = p + +class Outer3 : Outer.Middle.Nested() +class Outer2 { + class Nested2 : Outer.Middle.Nested() +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt.after b/idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt.after new file mode 100644 index 00000000000..97e1056fdca --- /dev/null +++ b/idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt.after @@ -0,0 +1,22 @@ +// NAME: Aliased +open class Outer{ + open class Middle { + open class Nested + } +} + +fun f2(){ + val o3 = Aliased() // (1) +} + +typealias Aliased = Outer.Middle.Nested + +val g3: Aliased = Aliased() //(2) + +fun f3(p: Aliased): Aliased = p + +class Outer3 : Aliased() +class Outer2 { + class Nested2 : Aliased() +} + diff --git a/idea/testData/refactoring/introduceTypeAlias/nestedClass.kt b/idea/testData/refactoring/introduceTypeAlias/nestedClass.kt new file mode 100644 index 00000000000..c5dcc133e6f --- /dev/null +++ b/idea/testData/refactoring/introduceTypeAlias/nestedClass.kt @@ -0,0 +1,17 @@ +// NAME: Aliased +open class Outer{ + open class Nested +} + +fun f2(){ + val o3 = Outer.Nested() // (1) +} + +val g3: Outer.Nested = Outer.Nested() //(2) + +fun f3(p: Outer.Nested): Outer.Nested = p + +class Outer3 : Outer.Nested() +class Outer2 { + class Nested2 : Outer.Nested() +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceTypeAlias/nestedClass.kt.after b/idea/testData/refactoring/introduceTypeAlias/nestedClass.kt.after new file mode 100644 index 00000000000..295de39d0db --- /dev/null +++ b/idea/testData/refactoring/introduceTypeAlias/nestedClass.kt.after @@ -0,0 +1,20 @@ +// NAME: Aliased +open class Outer{ + open class Nested +} + +fun f2(){ + val o3 = Aliased() // (1) +} + +typealias Aliased = Outer.Nested + +val g3: Aliased = Aliased() //(2) + +fun f3(p: Aliased): Aliased = p + +class Outer3 : Aliased() +class Outer2 { + class Nested2 : Aliased() +} + diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java index 70f96d58498..806b09867d8 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java @@ -3782,6 +3782,11 @@ public class ExtractionTestGenerated extends AbstractExtractionTest { runTest("idea/testData/refactoring/introduceTypeAlias/constructorCalls.kt"); } + @TestMetadata("deeplyNestedClass.kt") + public void testDeeplyNestedClass() throws Exception { + runTest("idea/testData/refactoring/introduceTypeAlias/deeplyNestedClass.kt"); + } + @TestMetadata("emptyName.kt") public void testEmptyName() throws Exception { runTest("idea/testData/refactoring/introduceTypeAlias/emptyName.kt"); @@ -3827,6 +3832,11 @@ public class ExtractionTestGenerated extends AbstractExtractionTest { runTest("idea/testData/refactoring/introduceTypeAlias/localWithVisibility.kt"); } + @TestMetadata("nestedClass.kt") + public void testNestedClass() throws Exception { + runTest("idea/testData/refactoring/introduceTypeAlias/nestedClass.kt"); + } + @TestMetadata("nestedTypesExtracted.kt") public void testNestedTypesExtracted() throws Exception { runTest("idea/testData/refactoring/introduceTypeAlias/nestedTypesExtracted.kt");