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
}