ReplaceWith intention could save generic type arguments

#KT-21195 Fixed
This commit is contained in:
Dmitry Gridin
2019-03-27 19:20:43 +07:00
parent b0f7ddd693
commit 88b0db6dd7
16 changed files with 199 additions and 2 deletions
@@ -49,9 +49,15 @@ class ClassUsageReplacementStrategy(
is KtUserType -> {
if (typeReplacement == null) return null
return {
val oldArgumentList = parent.typeArgumentList?.copy() as? KtTypeArgumentList
val replaced = parent.replaced(typeReplacement)
val newArgumentList = replaced.typeArgumentList
if (oldArgumentList != null && oldArgumentList.arguments.size == newArgumentList?.arguments?.size) {
newArgumentList.replace(oldArgumentList)
}
ShortenReferences.DEFAULT.process(replaced)
} //TODO: type arguments and type arguments of outer class are lost
}
}
is KtCallExpression -> {
@@ -80,7 +86,15 @@ class ClassUsageReplacementStrategy(
}
private fun replaceConstructorCallWithOtherTypeConstruction(callExpression: KtCallExpression): KtElement {
callExpression.calleeExpression!!.replace(typeReplacement!!.referenceExpression!!)
val referenceExpression = typeReplacement?.referenceExpression ?: error("Couldn't find referenceExpression")
callExpression.calleeExpression?.replace(referenceExpression)
val typeArgumentList = callExpression.typeArgumentList
if (typeArgumentList != null && typeReplacement.typeArguments.size != typeArgumentList.arguments.size) {
val newTypeArgumentList = typeReplacement.typeArgumentList
if (newTypeArgumentList != null) typeArgumentList.replace(newTypeArgumentList.copy())
else typeArgumentList.delete()
}
val expressionToReplace = callExpression.getQualifiedExpressionForSelectorOrThis()
val newExpression = if (typeReplacementQualifierAsExpression != null)
@@ -0,0 +1,11 @@
// "Replace with 'NewClass<T>'" "true"
package ppp
@Deprecated("renamed", ReplaceWith("NewClass<T>"))
class OldClass<T>
class NewClass<F>
fun foo() {
<caret>OldClass<Int>()
}
@@ -0,0 +1,11 @@
// "Replace with 'NewClass<T>'" "true"
package ppp
@Deprecated("renamed", ReplaceWith("NewClass<T>"))
class OldClass<T>
class NewClass<F>
fun foo() {
<caret>NewClass<Int>()
}
@@ -0,0 +1,11 @@
// "Replace with 'NewClass<Int>'" "true"
package ppp
@Deprecated("", ReplaceWith("NewClass<Int>"))
class OldClass<T, V>
class NewClass<F>
fun foo() {
<caret>OldClass<Int, String>()
}
@@ -0,0 +1,11 @@
// "Replace with 'NewClass<Int>'" "true"
package ppp
@Deprecated("", ReplaceWith("NewClass<Int>"))
class OldClass<T, V>
class NewClass<F>
fun foo() {
<caret>NewClass<Int>()
}
@@ -0,0 +1,11 @@
// "Replace with 'NewClass'" "true"
package ppp
@Deprecated("", ReplaceWith("NewClass"))
class OldClass<T, V>
class NewClass
fun foo() {
<caret>OldClass<Int, String>()
}
@@ -0,0 +1,11 @@
// "Replace with 'NewClass'" "true"
package ppp
@Deprecated("", ReplaceWith("NewClass"))
class OldClass<T, V>
class NewClass
fun foo() {
<caret>NewClass()
}
@@ -0,0 +1,12 @@
// "Replace with 'B<N>'" "true"
// WITH_RUNTIME
@Deprecated(message = "renamed", replaceWith = ReplaceWith("B<N>"))
typealias A<E> = List<E>
abstract class B<T> : List<T>
class F<G>
fun test() {
var x: <caret>A<F<Int>>
}
@@ -0,0 +1,12 @@
// "Replace with 'B<N>'" "true"
// WITH_RUNTIME
@Deprecated(message = "renamed", replaceWith = ReplaceWith("B<N>"))
typealias A<E> = List<E>
abstract class B<T> : List<T>
class F<G>
fun test() {
var x: <caret>B<F<Int>>
}
@@ -0,0 +1,10 @@
// "Replace with 'B<Int>'" "true"
@Deprecated("", ReplaceWith("B<Int>"))
class C<T, F>
class B<T>
fun foo() {
var c: <caret>C<Int, String>
}
@@ -0,0 +1,10 @@
// "Replace with 'B<Int>'" "true"
@Deprecated("", ReplaceWith("B<Int>"))
class C<T, F>
class B<T>
fun foo() {
var c: <caret>B<Int>
}
@@ -0,0 +1,10 @@
// "Replace with 'B'" "true"
@Deprecated("", ReplaceWith("B"))
class C<T, F>
class B
fun foo() {
var c: <caret>C<Int, String>
}
@@ -0,0 +1,10 @@
// "Replace with 'B'" "true"
@Deprecated("", ReplaceWith("B"))
class C<T, F>
class B
fun foo() {
var c: <caret>B
}
@@ -0,0 +1,9 @@
// "Replace with 'B<E>'" "true"
// WITH_RUNTIME
@Deprecated(message = "renamed", replaceWith = ReplaceWith("B<E>"))
typealias A<E> = List<E>
typealias B<E> = List<E>
val x: <caret>A<String> = emptyList()
@@ -0,0 +1,9 @@
// "Replace with 'B<E>'" "true"
// WITH_RUNTIME
@Deprecated(message = "renamed", replaceWith = ReplaceWith("B<E>"))
typealias A<E> = List<E>
typealias B<E> = List<E>
val x: B<String> = emptyList()
@@ -6041,6 +6041,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/constructorUsage4.kt");
}
@TestMetadata("constructorUsageWithTypeArgument.kt")
public void testConstructorUsageWithTypeArgument() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/constructorUsageWithTypeArgument.kt");
}
@TestMetadata("constructorUsageWithTypeArgument2.kt")
public void testConstructorUsageWithTypeArgument2() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/constructorUsageWithTypeArgument2.kt");
}
@TestMetadata("constructorUsageWithTypeArgument3.kt")
public void testConstructorUsageWithTypeArgument3() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/constructorUsageWithTypeArgument3.kt");
}
@TestMetadata("imports.kt")
public void testImports() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/imports.kt");
@@ -6081,6 +6096,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/inTypeArgument.kt");
}
@TestMetadata("innerType.kt")
public void testInnerType() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/innerType.kt");
}
@TestMetadata("nestedClassToNestedClass.kt")
public void testNestedClassToNestedClass() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/nestedClassToNestedClass.kt");
@@ -6091,6 +6111,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/noAnnotationConstructorUsage.kt");
}
@TestMetadata("noMatchTypeArgument.kt")
public void testNoMatchTypeArgument() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/noMatchTypeArgument.kt");
}
@TestMetadata("noMatchTypeArgument2.kt")
public void testNoMatchTypeArgument2() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/noMatchTypeArgument2.kt");
}
@TestMetadata("qualifiedClassName.kt")
public void testQualifiedClassName() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/qualifiedClassName.kt");
@@ -6559,6 +6589,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/typeAliases/typeAliasWithAllGenericParams.kt");
}
@TestMetadata("withTypeArgument.kt")
public void testWithTypeArgument() throws Exception {
runTest("idea/testData/quickfix/deprecatedSymbolUsage/typeAliases/withTypeArgument.kt");
}
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/typeAliases/wholeProject")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)