fun getRefactoringDescriptors()

in src/main/kotlin/org/arend/refactoring/changeSignature/ChangeSignatureRefactoringDescriptor.kt [283:458]


        fun getRefactoringDescriptors(
            locatedReferable: PsiLocatedReferable,
            newName: String,
            oldParameters: List<ParameterDescriptor>,
            newParameters: List<ParameterDescriptor>
        ): List<ChangeSignatureRefactoringDescriptor> {
            val refactoringDescriptors = ArrayList<ChangeSignatureRefactoringDescriptor>()
            when (locatedReferable) {
                is ArendClassField -> {
                    val thisParameter = ArendCodeInsightUtils.getThisParameter(locatedReferable) ?: throw IllegalStateException()
                    refactoringDescriptors.add(
                        ChangeSignatureRefactoringDescriptor(
                            locatedReferable,
                            Collections.singletonList(thisParameter) + oldParameters,
                            Collections.singletonList(
                                DefaultParameterDescriptorFactory.createThisParameter(
                                    thisParameter
                                )
                            ) + newParameters,
                            newName = if (locatedReferable.name != newName) newName else null
                        )
                    )
                }

                is ArendConstructor -> {
                    val thisParameter = ArendCodeInsightUtils.getThisParameterAsList(locatedReferable)
                    val thisNewParameter = thisParameter.firstOrNull()?.let {
                        Collections.singletonList(DefaultParameterDescriptorFactory.createThisParameter(it))
                    } ?: emptyList()
                    val data = locatedReferable.ancestor<ArendDefData>() ?: throw java.lang.IllegalStateException()
                    val dataParameters = (ArendCodeInsightUtils.getExternalParameters(data)
                        ?: emptyList()) + DefaultParameterDescriptorFactory.createFromTeles(data.parameters)
                    val calculatedSignature = ArendCodeInsightUtils.getPartialExpectedConstructorSignature(
                        locatedReferable,
                        dataParameters,
                        DefaultParameterDescriptorFactory.identityTransform(dataParameters)
                    )

                    refactoringDescriptors.add(
                        ChangeSignatureRefactoringDescriptor(
                            locatedReferable,
                            thisParameter + calculatedSignature.first + oldParameters,
                            thisNewParameter + calculatedSignature.second!! + newParameters,
                            newName = if (locatedReferable.name != newName) newName else null
                        )
                    )
                }

                is ArendDefClass -> {
                    val classDescendants = ClassDescendantsSearch(locatedReferable.project).getAllDescendants(
                        locatedReferable
                    )
                    for (classDescendant in classDescendants.filterIsInstance<ArendDefClass>().union(Collections.singletonList(
                        locatedReferable
                    ))) {
                        var modifiedArgumentStart = -1
                        var modifiedArgumentEnd = -1
                        val typecheckedNotImplementedFields = (classDescendant.tcReferable?.typechecked as? org.arend.core.definition.ClassDefinition)?.notImplementedFields
                        val externalParameterData = HashMap<String, ArendGroup>()
                        ArendCodeInsightUtils.getExternalParameters(classDescendant)?.forEach {
                            val externalScope = it.getExternalScope()
                            if (it.name != null && externalScope != null) externalParameterData[it.name] = externalScope
                        }

                        val descendantOldParameters: List<ParameterDescriptor>
                        val notImplementedFields = LinkedHashMap<String, ParameterDescriptor>()

                        if (typecheckedNotImplementedFields != null) {
                            descendantOldParameters = typecheckedNotImplementedFields.map {
                                val psiReferable = (it.referable as? DataLocatedReferable)?.data?.element
                                val (classParameterKind, externalScope) = when {
                                    psiReferable is ArendClassField -> Pair(ClassParameterKind.CLASS_FIELD, null)
                                    (it.parentClass.referable as? DataLocatedReferable)?.data?.element == classDescendant ->
                                        Pair(ClassParameterKind.OWN_PARAMETER, externalParameterData[it.name])
                                    else -> Pair(ClassParameterKind.INHERITED_PARAMETER, null)
                                }
                                if (psiReferable != null)
                                    DefaultParameterDescriptorFactory.createFromReferable(psiReferable, externalScope = externalScope, classParameterKind = classParameterKind)
                                else
                                    ParameterDescriptor(
                                        it.referable.refName,
                                        it.referable.isExplicitField,
                                        it.resultType.toString(),
                                        classParameterKind = classParameterKind,
                                        externalScope = externalScope
                                    )
                            }
                            for ((index, field) in typecheckedNotImplementedFields.withIndex())
                                if ((field.parentClass.referable as? DataLocatedReferable)?.data?.element == locatedReferable && (field.referable !is FieldDataLocatedReferable || field.referable.isParameterField)) {
                                    notImplementedFields[field.name] = descendantOldParameters[index]
                                    if (modifiedArgumentStart == -1) modifiedArgumentStart = index
                                    modifiedArgumentEnd = index
                                }
                        } else { // Fallback code for dumb mode
                            descendantOldParameters = ClassReferable.Helper.getNotImplementedFields(classDescendant).filterIsInstance<PsiElement>().withIndex().map { (index, field) ->
                                val classParent = field.ancestor<ArendDefClass>()!!
                                val descriptor = DefaultParameterDescriptorFactory.createFromReferable(field as FieldReferable)
                                if (classParent == locatedReferable) {
                                    notImplementedFields[field.refName] = descriptor
                                    if (modifiedArgumentStart == -1) modifiedArgumentStart = index
                                    modifiedArgumentEnd = index
                                }
                                descriptor
                            }
                        }

                        val prefix = if (modifiedArgumentStart > 0) descendantOldParameters.subList(0, modifiedArgumentStart) else emptyList()
                        val suffix = if (modifiedArgumentEnd + 1 < descendantOldParameters.size) descendantOldParameters.subList(modifiedArgumentEnd + 1, descendantOldParameters.size) else emptyList()

                        val centerPiece = newParameters.filter {parameterDescriptor ->
                            parameterDescriptor.oldParameter == null ||
                                    parameterDescriptor.isExternal() ||
                                    parameterDescriptor.oldParameter.isExternal() ||
                                    descendantOldParameters.mapNotNull { it.getReferable() }.toSet().contains( parameterDescriptor.oldParameter.getReferable() )
                        }.map {
                            val oldDescriptor: ParameterDescriptor? = it.oldParameter?.let { descriptor -> notImplementedFields[descriptor.name] }
                            val parameterKind =
                                if (classDescendant == locatedReferable) ClassParameterKind.OWN_PARAMETER else ClassParameterKind.INHERITED_PARAMETER
                            DefaultParameterDescriptorFactory.createNewParameter(it.isExplicit, oldDescriptor, oldDescriptor?.getExternalScope(), it.name, it.typeGetter, parameterKind)
                        }

                        val clazzNewParameters = prefix.map {
                            DefaultParameterDescriptorFactory.createNewParameter(it.isExplicit, it, it.getExternalScope(), it.getNameOrUnderscore(), it.typeGetter, it.classParameterKind)
                        } + centerPiece + suffix.map { DefaultParameterDescriptorFactory.createNewParameter(it.isExplicit, it, it.getExternalScope(), it.getNameOrUnderscore(), it.typeGetter, classParameterKind = it.classParameterKind) }
                        refactoringDescriptors.add(
                            ChangeSignatureRefactoringDescriptor(classDescendant, descendantOldParameters, clazzNewParameters, newName = if (locatedReferable == classDescendant) newName else null)
                        )
                    }
                }

                is ArendDefData, is ArendFunctionDefinition<*> -> {
                    val thisParameter = ArendCodeInsightUtils.getThisParameterAsList(locatedReferable)
                    val thisNewParameter =
                        thisParameter.firstOrNull()?.let { Collections.singletonList(DefaultParameterDescriptorFactory.createThisParameter(it)) }
                            ?: emptyList()
                    val mainRefactoringDescriptor = ChangeSignatureRefactoringDescriptor(
                        locatedReferable,
                        thisParameter + oldParameters,
                        thisNewParameter + newParameters,
                        newName = if (locatedReferable.name != newName) newName else null
                    )

                    refactoringDescriptors.add(mainRefactoringDescriptor)
                    val childDefinitions = getDefinitionsWithExternalParameters(locatedReferable as ParametersHolder)
                    for (childDef in childDefinitions) {
                        val childDefOldParameters =
                            ArendCodeInsightUtils.getParameterList(childDef as ParametersHolder).first!!
                        modifyExternalParameters(oldParameters, newParameters, childDef, childDefOldParameters)?.let {
                            refactoringDescriptors.add(it)
                        }
                    }

                    if (locatedReferable is ArendDefData && !mainRefactoringDescriptor.isSetOrOrderPreserved()) for (cons in locatedReferable.constructors) {
                        val constructorDataParameters =
                            ArendCodeInsightUtils.getPartialExpectedConstructorSignature(
                                cons,
                                oldParameters,
                                newParameters
                            )
                        val ownParameters = DefaultParameterDescriptorFactory.createFromTeles(cons.parameters)
                        val newOwnParameters = DefaultParameterDescriptorFactory.identityTransform(ownParameters)
                        refactoringDescriptors.add(
                            ChangeSignatureRefactoringDescriptor(
                                cons,
                                thisParameter + constructorDataParameters.first + ownParameters,
                                thisNewParameter + constructorDataParameters.second!! + newOwnParameters,
                            )
                        )
                    }

                }

                else -> throw NotImplementedError()
            }
            return refactoringDescriptors
        }