Introduce parameter: Do not substitute references which don't resolve to parameters or receivers of the target function #KT-7965 Fixed

This commit is contained in:
Alexey Sedunov
2015-06-11 14:41:58 +03:00
parent efb36f4a49
commit 09565c78c5
5 changed files with 53 additions and 6 deletions
@@ -57,6 +57,19 @@ public class JetParameterInfo(
defaultValueForCall!!.accept(
object : JetTreeVisitorVoid() {
private fun selfParameterOrNull(parameter: DeclarationDescriptor?): ValueParameterDescriptor? {
return if (parameter is ValueParameterDescriptor &&
parameter.getContainingDeclaration() == functionDescriptor) parameter else null
}
private fun selfReceiverOrNull(receiver: ThisReceiver?): DeclarationDescriptor? {
return when (receiver) {
functionDescriptor.getExtensionReceiverParameter()?.getValue(),
functionDescriptor.getDispatchReceiverParameter()?.getValue()-> receiver?.getDeclarationDescriptor()
else -> null
}
}
private fun getRelevantDescriptor(
expression: JetSimpleNameExpression,
ref: JetReference
@@ -64,18 +77,24 @@ public class JetParameterInfo(
val context = expression.analyze(BodyResolveMode.PARTIAL)
val descriptor = ref.resolveToDescriptors(context).singleOrNull()
if (descriptor is ValueParameterDescriptor) return descriptor
if (descriptor is ValueParameterDescriptor) return selfParameterOrNull(descriptor)
if (descriptor is PropertyDescriptor && functionDescriptor is ConstructorDescriptor) {
val parameter = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) as? JetParameter
return parameter?.let { context[BindingContext.VALUE_PARAMETER, it] }
return parameter?.let { selfParameterOrNull(context[BindingContext.VALUE_PARAMETER, it]) }
}
val resolvedCall = expression.getResolvedCall(context) ?: return null
(resolvedCall.getResultingDescriptor() as? ReceiverParameterDescriptor)?.let { return it }
(resolvedCall.getResultingDescriptor() as? ReceiverParameterDescriptor)?.let {
return when (it) {
functionDescriptor.getDispatchReceiverParameter(),
functionDescriptor.getExtensionReceiverParameter() -> it
else -> null
}
}
(resolvedCall.getExtensionReceiver() as? ThisReceiver)?.let { return it.getDeclarationDescriptor() }
(resolvedCall.getDispatchReceiver() as? ThisReceiver)?.let { return it.getDeclarationDescriptor() }
selfReceiverOrNull(resolvedCall.getExtensionReceiver() as? ThisReceiver)?.let { return it }
selfReceiverOrNull(resolvedCall.getDispatchReceiver() as? ThisReceiver)?.let { return it }
return null
}
@@ -120,7 +120,11 @@ fun IntroduceParameterDescriptor.performRefactoring() {
return originalDescriptor.modify { methodDescriptor ->
if (!withDefaultValue) {
val parameters = callable.getValueParameters()
parametersToRemove.map { parameters.indexOf(it) }.sortDescending().forEach { methodDescriptor.removeParameter(it) }
val withReceiver = methodDescriptor.receiver != null
parametersToRemove
.map { parameters.indexOf(it) + if (withReceiver) 1 else 0 }
.sortDescending()
.forEach { methodDescriptor.removeParameter(it) }
}
val parameterInfo = JetParameterInfo(functionDescriptor = callableDescriptor,
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// WITH_DEFAULT_VALUE: false
fun a() {
1.b(2)
}
fun Int.foo(f: Int.(Int) -> Int) = this
fun Int.b(n: Int) = <selection>n.foo { it + this + n + this@b }</selection> + 1
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// WITH_DEFAULT_VALUE: false
fun a() {
1.b(2.foo { it + this + 2 + 1 })
}
fun Int.foo(f: Int.(Int) -> Int) = this
fun Int.b(i: Int) = i + 1
@@ -2401,6 +2401,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
doIntroduceSimpleParameterTest(fileName);
}
@TestMetadata("foreignParameterRef.kt")
public void testForeignParameterRef() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/foreignParameterRef.kt");
doIntroduceSimpleParameterTest(fileName);
}
@TestMetadata("fun.kt")
public void testFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/fun.kt");