KT-8169 Strange exception when replacing function call to its only argument

#KT-8169 Fixed
This commit is contained in:
Valentin Kipyatkov
2015-06-25 11:00:59 +02:00
parent 463b0cda79
commit 498e746689
6 changed files with 64 additions and 13 deletions
@@ -153,21 +153,21 @@ public abstract class DeprecatedSymbolUsageFixBase(
receiver?.mark(RECEIVER_VALUE_KEY) receiver?.mark(RECEIVER_VALUE_KEY)
val wrapper = ConstructedExpressionWrapper(replacement.expression, expressionToBeReplaced, bindingContext)
//TODO: this@ //TODO: this@
for (thisExpression in replacement.expression.collectDescendantsOfType<JetThisExpression>()) { for (thisExpression in replacement.expression.collectDescendantsOfType<JetThisExpression>()) {
if (receiver != null) { if (receiver != null) {
thisExpression.replace(receiver) wrapper.replaceExpression(thisExpression, receiver)
} }
else { else {
thisExpression.mark(RECEIVER_VALUE_KEY) thisExpression.mark(RECEIVER_VALUE_KEY)
} }
} }
val introduceValuesForParameters = processValueParameterUsages(resolvedCall, replacement, bindingContext, project) val introduceValuesForParameters = wrapper.processValueParameterUsages(resolvedCall, project)
processTypeParameterUsages(resolvedCall, replacement) wrapper.processTypeParameterUsages(resolvedCall)
val wrapper = ConstructedExpressionWrapper(replacement.expression, expressionToBeReplaced, bindingContext)
if (qualifiedExpression is JetSafeQualifiedExpression) { if (qualifiedExpression is JetSafeQualifiedExpression) {
wrapper.wrapExpressionForSafeCall(receiver!!, receiverType) wrapper.wrapExpressionForSafeCall(receiver!!, receiverType)
@@ -209,10 +209,8 @@ public abstract class DeprecatedSymbolUsageFixBase(
return resultRange.last as JetExpression return resultRange.last as JetExpression
} }
private fun processValueParameterUsages( private fun ConstructedExpressionWrapper.processValueParameterUsages(
resolvedCall: ResolvedCall<out CallableDescriptor>, resolvedCall: ResolvedCall<out CallableDescriptor>,
replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression,
bindingContext: BindingContext,
project: Project project: Project
): Collection<IntroduceValueForParameter> { ): Collection<IntroduceValueForParameter> {
val introduceValuesForParameters = ArrayList<IntroduceValueForParameter>() val introduceValuesForParameters = ArrayList<IntroduceValueForParameter>()
@@ -225,7 +223,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
argument.expression.put(PARAMETER_VALUE_KEY, parameter) argument.expression.put(PARAMETER_VALUE_KEY, parameter)
val parameterName = parameter.getName() val parameterName = parameter.getName()
val usages = replacement.expression.collectDescendantsOfType<JetExpression> { val usages = expression.collectDescendantsOfType<JetExpression> {
it[ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY] == parameterName it[ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY] == parameterName
} }
usages.forEach { usages.forEach {
@@ -236,7 +234,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
if (argument.isDefaultValue) { if (argument.isDefaultValue) {
usageArgument?.mark(DEFAULT_PARAMETER_VALUE_KEY) usageArgument?.mark(DEFAULT_PARAMETER_VALUE_KEY)
} }
it.replace(argument.expression) replaceExpression(it, argument.expression)
} }
//TODO: sometimes we need to add explicit type arguments here because we don't have expected type in the new context //TODO: sometimes we need to add explicit type arguments here because we don't have expected type in the new context
@@ -254,7 +252,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
val value: JetExpression, val value: JetExpression,
val valueType: JetType?) val valueType: JetType?)
private fun processTypeParameterUsages(resolvedCall: ResolvedCall<out CallableDescriptor>, replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression) { private fun ConstructedExpressionWrapper.processTypeParameterUsages(resolvedCall: ResolvedCall<out CallableDescriptor>) {
val typeParameters = resolvedCall.getResultingDescriptor().getOriginal().getTypeParameters() val typeParameters = resolvedCall.getResultingDescriptor().getOriginal().getTypeParameters()
val callElement = resolvedCall.getCall().getCallElement() val callElement = resolvedCall.getCall().getCallElement()
@@ -264,7 +262,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
for ((index, typeParameter) in typeParameters.withIndex()) { for ((index, typeParameter) in typeParameters.withIndex()) {
val parameterName = typeParameter.getName() val parameterName = typeParameter.getName()
val usages = replacement.expression.collectDescendantsOfType<JetExpression> { val usages = expression.collectDescendantsOfType<JetExpression> {
it[ReplaceWithAnnotationAnalyzer.TYPE_PARAMETER_USAGE_KEY] == parameterName it[ReplaceWithAnnotationAnalyzer.TYPE_PARAMETER_USAGE_KEY] == parameterName
} }
@@ -285,7 +283,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
} }
else { else {
//TODO: tests for this? //TODO: tests for this?
usage.replace(JetPsiFactory(usage).createExpression(typeElement.getText())) replaceExpression(usage, JetPsiFactory(usage).createExpression(typeElement.getText()))
} }
} }
} }
@@ -639,6 +637,15 @@ public abstract class DeprecatedSymbolUsageFixBase(
val psiFactory = JetPsiFactory(expressionToBeReplaced) val psiFactory = JetPsiFactory(expressionToBeReplaced)
public fun replaceExpression(oldExpression: JetExpression, newExpression: JetExpression): JetExpression {
assert(expression.isAncestor(oldExpression))
val result = oldExpression.replace(newExpression) as JetExpression
if (oldExpression == expression) {
expression = result
}
return result
}
public fun introduceValue( public fun introduceValue(
value: JetExpression, value: JetExpression,
valueType: JetType?, valueType: JetType?,
@@ -0,0 +1,7 @@
// "Replace with 'p'" "true"
deprecated("", ReplaceWith("p"))
fun oldFun(p: Int): Int = p
fun foo() {
<caret>oldFun(0)
}
@@ -0,0 +1,7 @@
// "Replace with 'p'" "true"
deprecated("", ReplaceWith("p"))
fun oldFun(p: Int): Int = p
fun foo() {
<caret>0
}
@@ -0,0 +1,9 @@
// "Replace with 'this'" "true"
class C {
deprecated("", ReplaceWith("this"))
fun oldFun(): C = this
}
fun foo() {
C().<caret>oldFun()
}
@@ -0,0 +1,9 @@
// "Replace with 'this'" "true"
class C {
deprecated("", ReplaceWith("this"))
fun oldFun(): C = this
}
fun foo() {
<caret>C()
}
@@ -3034,6 +3034,18 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("replaceCallWithArgument.kt")
public void testReplaceCallWithArgument() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/replaceCallWithArgument.kt");
doTest(fileName);
}
@TestMetadata("replaceCallWithReceiver.kt")
public void testReplaceCallWithReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/replaceCallWithReceiver.kt");
doTest(fileName);
}
@TestMetadata("shortenReferences.kt") @TestMetadata("shortenReferences.kt")
public void testShortenReferences() throws Exception { public void testShortenReferences() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/shortenReferences.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/shortenReferences.kt");