diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinParameterInfo.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinParameterInfo.kt index ed025e8c86a..612a9d2b3a9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinParameterInfo.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinParameterInfo.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.types.isError -import java.util.* class KotlinParameterInfo @JvmOverloads constructor( val callableDescriptor: CallableDescriptor, @@ -47,66 +46,7 @@ class KotlinParameterInfo @JvmOverloads constructor( private fun collectDefaultValueParameterReferences(defaultValueForCall: KtExpression?): Map { val file = defaultValueForCall?.containingFile as? KtFile ?: return emptyMap() if (!file.isPhysical && file.analysisContext == null) return emptyMap() - - val project = file.project - val map = LinkedHashMap() - - defaultValueForCall.accept( - object : KtTreeVisitorVoid() { - private fun compareDescriptors(currentDescriptor: DeclarationDescriptor?, originalDescriptor: DeclarationDescriptor?): Boolean { - return compareDescriptors(project, currentDescriptor, originalDescriptor) - } - - private fun takeIfParameterOfSelf(parameter: DeclarationDescriptor?): ValueParameterDescriptor? { - return (parameter as? ValueParameterDescriptor) - ?.takeIf { compareDescriptors(it.containingDeclaration, callableDescriptor) } - } - - private fun takeIfReceiverOfSelf(receiverDescriptor: DeclarationDescriptor?): DeclarationDescriptor? { - return receiverDescriptor?.takeIf { - compareDescriptors(it, callableDescriptor.extensionReceiverParameter?.containingDeclaration) - || compareDescriptors(it, callableDescriptor.dispatchReceiverParameter?.containingDeclaration) - } - } - - private fun takeIfReceiverOfSelf(receiver: ImplicitReceiver?): DeclarationDescriptor? { - return takeIfReceiverOfSelf(receiver?.declarationDescriptor) - } - - private fun getRelevantDescriptor(expression: KtSimpleNameExpression, ref: KtReference): DeclarationDescriptor? { - val context = expression.analyze(BodyResolveMode.PARTIAL) - - val descriptor = ref.resolveToDescriptors(context).singleOrNull() - if (descriptor is ValueParameterDescriptor) { - return takeIfParameterOfSelf(descriptor) - } - - if (descriptor is PropertyDescriptor && callableDescriptor is ConstructorDescriptor) { - val parameter = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) - if (parameter is KtParameter) { - return takeIfParameterOfSelf(context[BindingContext.VALUE_PARAMETER, parameter]) - } - } - - val resolvedCall = expression.getResolvedCall(context) ?: return null - (resolvedCall.resultingDescriptor as? ReceiverParameterDescriptor)?.let { - return if (takeIfReceiverOfSelf(it.containingDeclaration) != null) it else null - } - - takeIfReceiverOfSelf(resolvedCall.extensionReceiver as? ImplicitReceiver)?.let { return it } - takeIfReceiverOfSelf(resolvedCall.dispatchReceiver as? ImplicitReceiver)?.let { return it } - - return null - } - - override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) { - val ref = expression.mainReference - val descriptor = getRelevantDescriptor(expression, ref) ?: return - map[ref] = descriptor - } - } - ) - return map + return CollectParameterRefsVisitor(callableDescriptor, defaultValueForCall).run() } override fun getOldIndex(): Int = originalIndex @@ -234,4 +174,68 @@ class KotlinParameterInfo @JvmOverloads constructor( return newParameter } + + private class CollectParameterRefsVisitor( + private val callableDescriptor: CallableDescriptor, + private val expressionToProcess: KtExpression + ) : KtTreeVisitorVoid() { + private val refs = LinkedHashMap() + private val bindingContext = expressionToProcess.analyze(BodyResolveMode.PARTIAL) + private val project = expressionToProcess.project + + fun run(): Map { + expressionToProcess.accept(this) + return refs + } + + override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) { + val ref = expression.mainReference + val descriptor = targetToCollect(expression, ref) ?: return + refs[ref] = descriptor + } + + private fun targetToCollect(expression: KtSimpleNameExpression, ref: KtReference): DeclarationDescriptor? { + val descriptor = ref.resolveToDescriptors(bindingContext).singleOrNull() + if (descriptor is ValueParameterDescriptor) { + return takeIfOurParameter(descriptor) + } + + if (descriptor is PropertyDescriptor && callableDescriptor is ConstructorDescriptor) { + val parameter = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) + if (parameter is KtParameter) { + return takeIfOurParameter(bindingContext[BindingContext.VALUE_PARAMETER, parameter]) + } + } + + val resolvedCall = expression.getResolvedCall(bindingContext) ?: return null + (resolvedCall.resultingDescriptor as? ReceiverParameterDescriptor)?.let { + return if (takeIfOurReceiver(it.containingDeclaration) != null) it else null + } + + takeIfOurReceiver(resolvedCall.extensionReceiver as? ImplicitReceiver)?.let { return it } + takeIfOurReceiver(resolvedCall.dispatchReceiver as? ImplicitReceiver)?.let { return it } + + return null + } + + private fun compareDescriptors(currentDescriptor: DeclarationDescriptor?, originalDescriptor: DeclarationDescriptor?): Boolean { + return compareDescriptors(project, currentDescriptor, originalDescriptor) + } + + private fun takeIfOurParameter(parameter: DeclarationDescriptor?): ValueParameterDescriptor? { + return (parameter as? ValueParameterDescriptor) + ?.takeIf { compareDescriptors(it.containingDeclaration, callableDescriptor) } + } + + private fun takeIfOurReceiver(receiverDescriptor: DeclarationDescriptor?): DeclarationDescriptor? { + return receiverDescriptor?.takeIf { + compareDescriptors(it, callableDescriptor.extensionReceiverParameter?.containingDeclaration) + || compareDescriptors(it, callableDescriptor.dispatchReceiverParameter?.containingDeclaration) + } + } + + private fun takeIfOurReceiver(receiver: ImplicitReceiver?): DeclarationDescriptor? { + return takeIfOurReceiver(receiver?.declarationDescriptor) + } + } }