[FIR generator] Extract BaseTransformerTypeFinder into the common module

We want to use it in other tree generators.
This commit is contained in:
Sergej Jaskiewicz
2023-11-14 12:46:40 +01:00
committed by Space Team
parent 7787b53b4a
commit 62d32471e1
17 changed files with 126 additions and 87 deletions
@@ -79,6 +79,25 @@ abstract class AbstractElement<Element, Field>(
abstract override val transformableChildren: List<Field>
/**
* A custom return type of the corresponding transformer method for this element.
*/
var transformerReturnType: Element? = null
/**
* @see org.jetbrains.kotlin.generators.tree.detectBaseTransformerTypes
*/
internal var baseTransformerType: Element? = null
/**
* The return type of the corresponding transformer method for this element.
*
* By default, computed using [org.jetbrains.kotlin.generators.tree.detectBaseTransformerTypes], but can be customizaed via
* [transformerReturnType]
*/
val transformerClass: Element
get() = transformerReturnType ?: baseTransformerType ?: element
final override fun get(fieldName: String): Field? {
return allFields.firstOrNull { it.name == fieldName }
}
@@ -38,8 +38,19 @@ abstract class AbstractField {
var fromParent: Boolean = false
/**
* Whether this field can contain an element either directly or e.g. in a list.
*/
open val containsElement: Boolean
get() = typeRef is ElementOrRef<*, *> || this is ListField && baseType is ElementOrRef<*, *>
open val defaultValueInImplementation: String? get() = null
/**
* @see org.jetbrains.kotlin.generators.tree.detectBaseTransformerTypes
*/
var useInBaseTransformerDetection = true
override fun toString(): String {
return name
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.generators.tree
/**
* A field that is used to store a list with arbitrary elements.
*/
interface ListField {
/**
* The element type of the list.
*/
val baseType: TypeRef
/**
* The list type of the field, e.g. [List] or [MutableList].
*/
val listType: ClassRef<PositionTypeParameterRef>
val typeRef: ClassRef<PositionTypeParameterRef>
get() = listType.withArgs(baseType)
}
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.generators.tree
fun <Element : AbstractElement<Element, *>> Element.traverseParents(block: (Element) -> Unit) {
block(this)
elementParents.forEach { it.element.traverseParents(block) }
}
/**
* For each tree element, sets its [AbstractElement.baseTransformerType] to one of it parents if that parent type is used at least once as
* a type of a field, except when that field is explicitly opted out of it via
* [AbstractField.useInBaseTransformerDetection].
*/
fun <Element : AbstractElement<Element, *>> detectBaseTransformerTypes(model: Model<Element>) {
val usedAsFieldType = hashSetOf<AbstractElement<*, *>>()
for (element in model.elements) {
for (field in element.allFields.filter { it.containsElement }) {
if (!field.useInBaseTransformerDetection) continue
val fieldElement = (field.typeRef as? ElementOrRef<*, *>)?.element
?: ((field as? ListField)?.baseType as? ElementOrRef<*, *>)?.element
?: continue
if (fieldElement.isRootElement) continue
usedAsFieldType.add(fieldElement)
}
}
for (element in model.elements) {
element.traverseParents {
if (it in usedAsFieldType) {
element.baseTransformerType = it
return@traverseParents
}
}
}
}