[IR generator] Simplify computation of walkable children

Don't require to specify them explicitly via `isChild` in IR generator,
instead test the field type whether it is an element.
This commit is contained in:
Sergej Jaskiewicz
2023-11-16 19:01:36 +01:00
committed by Space Team
parent ad4e97154f
commit 5f04bc8a27
7 changed files with 152 additions and 161 deletions
@@ -26,11 +26,19 @@ interface FieldContainer<out Field : AbstractField<*>> {
val hasTransformChildrenMethod: Boolean
get() = false
/**
* Allows to override the order in which the specified children will be visited in `acceptChildren`/`transformChildren` methods.
*/
val childrenOrderOverride: List<String>?
get() = null
/**
* The fields on which to run the visitor in generated `acceptChildren` methods.
*/
val walkableChildren: List<Field>
get() = allFields.filter { it.containsElement && !it.withGetter && it.needAcceptAndTransform }
get() = allFields
.filter { it.containsElement && !it.withGetter && it.needAcceptAndTransform }
.reorderFieldsIfNecessary(childrenOrderOverride)
/**
* The fields on which to run the transformer in generated `transformChildren` methods.
@@ -5,9 +5,26 @@
package org.jetbrains.kotlin.generators.tree
/**
* Runs [block] on this element and all its parents recursively.
*/
fun <Element : AbstractElement<Element, *>> Element.traverseParents(block: (Element) -> Unit) {
block(this)
elementParents.forEach { it.element.traverseParents(block) }
traverseParentsUntil { block(it); false }
}
/**
* Runs [block] on this element and all its parents recursively.
*
* If [block] returns `true` at any point, aborts iteration and returns `true`.
*
* If [block] always returns `false`, visits all the parents and returns `false`.
*/
fun <Element : AbstractElement<Element, *>> Element.traverseParentsUntil(block: (Element) -> Boolean): Boolean {
if (block(this)) return true
for (parent in elementParents) {
if (parent.element.traverseParentsUntil(block)) return true
}
return false
}
/**
@@ -46,4 +63,14 @@ operator fun <K, V, U> MutableMap<K, MutableMap<V, U>>.set(k1: K, k2: V, value:
operator fun <K, V, U> Map<K, Map<V, U>>.get(k1: K, k2: V): U {
return getValue(k1).getValue(k2)
}
}
internal fun <Field : AbstractField<*>> List<Field>.reorderFieldsIfNecessary(order: List<String>?): List<Field> =
if (order == null) {
this
} else {
sortedBy {
val position = order.indexOf(it.name)
if (position < 0) order.size else position
}
}