[IR] Final preparation to autogenerate IR declaration implementations

IR expressions are left out for now, because unlike declarations,
which are mostly created via IrFactory, expressions' constructors are
widely used, and it's hard to replicate the exact signatures of those
constructors with the tree generator.

Therefore, some other approach is expected to be taken when generating
them in the future.

^KT-65773 In Progress
This commit is contained in:
Wojciech Litewka
2024-02-21 16:40:11 +01:00
committed by Space Team
parent 451c51c849
commit 6cdddaacb0
13 changed files with 259 additions and 57 deletions
@@ -629,7 +629,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
override fun configureAllImplementations(model: Model) {
configureFieldInAllImplementations(
field = "controlFlowGraphReference",
fieldName = "controlFlowGraphReference",
implementationPredicate = { it.typeName != "FirAnonymousFunctionImpl" }
) {
defaultNull(it)
@@ -661,7 +661,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
"FirInaccessibleReceiverExpressionImpl"
)
configureFieldInAllImplementations(
field = "typeRef",
fieldName = "typeRef",
implementationPredicate = { it.typeName !in implementationWithConfigurableTypeRef },
fieldPredicate = { it.defaultValueInImplementation == null }
) {
@@ -670,7 +670,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
}
configureFieldInAllImplementations(
field = "lValueTypeRef",
fieldName = "lValueTypeRef",
implementationPredicate = { it.typeName in "FirVariableAssignmentImpl" },
fieldPredicate = { it.defaultValueInImplementation == null }
) {
@@ -27,6 +27,9 @@ private class ImplementationFieldPrinter(printer: SmartPrinter) : AbstractFieldP
override fun forceMutable(field: FieldWithDefault): Boolean = field.isMutable && field.isMutableOrEmptyIfList()
override fun actualTypeOfField(field: FieldWithDefault) = field.getMutableType()
override val wrapOptInAnnotations
get() = true
}
internal class ImplementationPrinter(
@@ -5,16 +5,139 @@
package org.jetbrains.kotlin.ir.generator
import org.jetbrains.kotlin.generators.tree.StandardTypes
import org.jetbrains.kotlin.ir.generator.config.AbstractIrTreeImplementationConfigurator
import org.jetbrains.kotlin.ir.generator.model.Element
import org.jetbrains.kotlin.ir.generator.model.ListField
object ImplementationConfigurator : AbstractIrTreeImplementationConfigurator() {
override fun configure(model: Model): Unit = with(IrTree) {
impl(simpleFunction)
impl(property)
impl(anonymousInitializer) {
implementation.doPrint = false
}
impl(simpleFunction) {
implementation.doPrint = false
}
impl(functionWithLateBinding) {
implementation.doPrint = false
}
impl(constructor) {
implementation.doPrint = false
}
impl(field) {
implementation.doPrint = false
}
impl(property) {
implementation.doPrint = false
}
impl(propertyWithLateBinding) {
implementation.doPrint = false
}
impl(localDelegatedProperty) {
implementation.doPrint = false
}
impl(typeParameter) {
implementation.doPrint = false
}
impl(valueParameter) {
implementation.doPrint = false
}
impl(variable) {
implementation.doPrint = false
}
impl(`class`) {
implementation.doPrint = false
}
impl(enumEntry) {
implementation.doPrint = false
}
impl(script) {
implementation.doPrint = false
}
impl(moduleFragment) {
implementation.doPrint = false
}
impl(errorDeclaration) {
implementation.doPrint = false
}
impl(externalPackageFragment) {
implementation.doPrint = false
}
impl(file) {
implementation.doPrint = false
}
impl(typeAlias) {
implementation.doPrint = false
}
}
override fun configureAllImplementations(model: Model) {
// Use configureFieldInAllImplementations to customize certain fields in all implementation classes
configureFieldInAllImplementations("parent") {
isLateinit("parent")
isMutable("parent")
}
configureFieldInAllImplementations("attributeOwnerId") {
default(it, "this")
}
configureFieldInAllImplementations("originalBeforeInline") {
defaultNull(it)
}
configureFieldInAllImplementations("metadata") {
defaultNull(it)
}
configureFieldInAllImplementations("annotations") {
defaultEmptyList(it)
}
configureFieldInAllImplementations("overriddenSymbols") {
defaultEmptyList(it)
}
configureFieldInAllImplementations("typeParameters") {
defaultEmptyList(it)
}
configureFieldInAllImplementations("statements") {
default(it, "ArrayList(2)")
}
configureFieldInAllImplementations("descriptor", { impl -> impl.allFields.any { it.name == "symbol" } }) {
default(it, "symbol.descriptor", withGetter = true)
}
configureFieldInAllImplementations(
fieldName = null,
fieldPredicate = { it is ListField && it.isChild && it.listType == StandardTypes.mutableList }
) {
default(it, "ArrayList()")
}
// Generation of implementation classes of IrExpression are left out for subsequent MR, as a part of KT-65773.
for (element in model.elements) {
if (element.category == Element.Category.Expression) {
for (implementation in element.implementations) {
implementation.doPrint = false
}
}
}
}
}
@@ -35,6 +35,7 @@ fun main(args: Array<String>) {
typeTransformerType to ::TypeTransformerPrinter.bind(model.rootElement),
),
ImplementationConfigurator,
createImplementationPrinter = ::ImplementationPrinter,
enableBaseTransformerTypeDetection = false,
addFiles = { add(printFactory(generationPath, model)) }
)
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef
class Element(
name: String,
override val propertyName: String,
category: Category,
val category: Category,
) : AbstractElement<Element, Field, Implementation>(name) {
enum class Category(private val packageDir: String, val defaultVisitorParam: String) {
@@ -7,8 +7,19 @@ package org.jetbrains.kotlin.ir.generator.model
import org.jetbrains.kotlin.generators.tree.AbstractImplementation
import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.generators.tree.ImportCollector
import org.jetbrains.kotlin.utils.SmartPrinter
class Implementation(element: Element, name: String?) : AbstractImplementation<Implementation, Element, Field>(element, name) {
override val allFields
get() = element.allFields
override val allFields: List<Field> = element.allFields.map { it.copy() }
override var kind: ImplementationKind? = ImplementationKind.FinalClass
var generationCallback: (context(ImportCollector) SmartPrinter.() -> Unit)? = null
override var doPrint = true
init {
isPublic = true
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2024 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.ir.generator.print
import com.intellij.psi.util.PsiExpressionTrimRenderer.render
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.printBlock
import org.jetbrains.kotlin.ir.generator.IrTree
import org.jetbrains.kotlin.ir.generator.IrTree.parent
import org.jetbrains.kotlin.ir.generator.irImplementationDetailType
import org.jetbrains.kotlin.ir.generator.model.*
import org.jetbrains.kotlin.utils.SmartPrinter
internal class ImplementationPrinter(printer: SmartPrinter) : AbstractImplementationPrinter<Implementation, Element, Field>(printer) {
override fun makeFieldPrinter(printer: SmartPrinter) = object : AbstractFieldPrinter<Field>(printer) {
override fun forceMutable(field: Field) = field.isMutable
}
override val pureAbstractElementType: ClassRef<*>
get() = org.jetbrains.kotlin.ir.generator.elementBaseType
override val implementationOptInAnnotation: ClassRef<*>
get() = irImplementationDetailType
override val separateFieldsWithBlankLine: Boolean
get() = true
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods(implementation: Implementation) {
implementation.generationCallback?.invoke(this@ImportCollector, this)
if (
implementation.element.traverseParentsUntil { it == IrTree.symbolOwner } &&
!implementation.element.let { it == IrTree.propertyWithLateBinding || it == IrTree.functionWithLateBinding }
) {
val symbolField = implementation["symbol"]
if (symbolField != null) {
println()
print("init")
printBlock {
println("${symbolField.name}.bind(this)")
}
}
}
}
}