Introduce Type Alias: Fix replacement of references to nested classes
#KT-15159 Fixed
This commit is contained in:
+17
-4
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
|||||||
import org.jetbrains.kotlin.idea.core.CollectingNameValidator
|
import org.jetbrains.kotlin.idea.core.CollectingNameValidator
|
||||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||||
import org.jetbrains.kotlin.idea.core.compareDescriptors
|
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.refactoring.introduce.insertDeclaration
|
||||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
|
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
|
||||||
@@ -164,23 +165,35 @@ fun findDuplicates(typeAlias: KtTypeAlias): Map<KotlinPsiRange, () -> Unit> {
|
|||||||
|
|
||||||
val psiFactory = KtPsiFactory(typeAlias)
|
val psiFactory = KtPsiFactory(typeAlias)
|
||||||
|
|
||||||
|
fun replaceTypeElement(occurrence: KtTypeElement, typeArgumentsText: String) {
|
||||||
|
occurrence.replace(psiFactory.createType("$aliasName$typeArgumentsText").typeElement!!)
|
||||||
|
}
|
||||||
|
|
||||||
fun replaceOccurrence(occurrence: PsiElement, arguments: List<KtTypeElement>) {
|
fun replaceOccurrence(occurrence: PsiElement, arguments: List<KtTypeElement>) {
|
||||||
val typeArgumentsText = if (arguments.isNotEmpty()) "<${arguments.joinToString { it.text }}>" else ""
|
val typeArgumentsText = if (arguments.isNotEmpty()) "<${arguments.joinToString { it.text }}>" else ""
|
||||||
when (occurrence) {
|
when (occurrence) {
|
||||||
is KtTypeElement -> {
|
is KtTypeElement -> {
|
||||||
occurrence.replace(psiFactory.createType("$aliasName$typeArgumentsText").typeElement!!)
|
replaceTypeElement(occurrence, typeArgumentsText)
|
||||||
|
}
|
||||||
|
|
||||||
|
is KtSuperTypeCallEntry -> {
|
||||||
|
occurrence.calleeExpression.typeReference?.typeElement?.let { replaceTypeElement(it, typeArgumentsText) }
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtCallElement -> {
|
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()) {
|
if (arguments.isNotEmpty()) {
|
||||||
val newTypeArgumentList = psiFactory.createTypeArguments(typeArgumentsText)
|
val newTypeArgumentList = psiFactory.createTypeArguments(typeArgumentsText)
|
||||||
typeArgumentList?.replace(newTypeArgumentList) ?: occurrence.addAfter(newTypeArgumentList, occurrence)
|
typeArgumentList?.replace(newTypeArgumentList) ?: callExpression.addAfter(newTypeArgumentList, callExpression.calleeExpression)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
typeArgumentList?.delete()
|
typeArgumentList?.delete()
|
||||||
}
|
}
|
||||||
occurrence.calleeExpression?.replace(psiFactory.createExpression(aliasName))
|
callExpression.calleeExpression?.replace(psiFactory.createExpression(aliasName))
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtExpression -> occurrence.replace(psiFactory.createExpression(aliasName))
|
is KtExpression -> occurrence.replace(psiFactory.createExpression(aliasName))
|
||||||
|
|||||||
@@ -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: <caret>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()
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// NAME: Aliased
|
||||||
|
open class Outer{
|
||||||
|
open class Nested
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f2(){
|
||||||
|
val o3 = Outer.Nested() // (1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val g3: <caret>Outer.Nested = Outer.Nested() //(2)
|
||||||
|
|
||||||
|
fun f3(p: Outer.Nested): Outer.Nested = p
|
||||||
|
|
||||||
|
class Outer3 : Outer.Nested()
|
||||||
|
class Outer2 {
|
||||||
|
class Nested2 : Outer.Nested()
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
|
|
||||||
+10
@@ -3782,6 +3782,11 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
|||||||
runTest("idea/testData/refactoring/introduceTypeAlias/constructorCalls.kt");
|
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")
|
@TestMetadata("emptyName.kt")
|
||||||
public void testEmptyName() throws Exception {
|
public void testEmptyName() throws Exception {
|
||||||
runTest("idea/testData/refactoring/introduceTypeAlias/emptyName.kt");
|
runTest("idea/testData/refactoring/introduceTypeAlias/emptyName.kt");
|
||||||
@@ -3827,6 +3832,11 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
|||||||
runTest("idea/testData/refactoring/introduceTypeAlias/localWithVisibility.kt");
|
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")
|
@TestMetadata("nestedTypesExtracted.kt")
|
||||||
public void testNestedTypesExtracted() throws Exception {
|
public void testNestedTypesExtracted() throws Exception {
|
||||||
runTest("idea/testData/refactoring/introduceTypeAlias/nestedTypesExtracted.kt");
|
runTest("idea/testData/refactoring/introduceTypeAlias/nestedTypesExtracted.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user