[IR generator] Move each visitor printer into its own file

This commit is contained in:
Sergej Jaskiewicz
2023-12-05 14:42:22 +01:00
committed by Space Team
parent 8c75526130
commit e4078d163b
6 changed files with 448 additions and 355 deletions
@@ -0,0 +1,69 @@
/*
* 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.ir.generator.print
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.GeneratedFile
import org.jetbrains.kotlin.generators.tree.printer.printBlock
import org.jetbrains.kotlin.ir.generator.elementTransformerType
import org.jetbrains.kotlin.ir.generator.elementVisitorType
import org.jetbrains.kotlin.ir.generator.model.Element
import org.jetbrains.kotlin.ir.generator.model.Field
import org.jetbrains.kotlin.ir.generator.model.Model
import org.jetbrains.kotlin.utils.SmartPrinter
import org.jetbrains.kotlin.utils.withIndent
import java.io.File
private class TransformerPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
val rootElement: Element,
) : AbstractVisitorPrinter<Element, Field>(printer) {
override val visitorSuperType: ClassRef<PositionTypeParameterRef>
get() = elementVisitorType.withArgs(rootElement, dataTypeVariable)
override val visitorTypeParameters: List<TypeVariable>
get() = listOf(dataTypeVariable)
override val visitorDataType: TypeRef
get() = dataTypeVariable
override fun visitMethodReturnType(element: Element) = element.getTransformExplicitType()
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
context(ImportCollector)
override fun printMethodsForElement(element: Element) {
printer.run {
val parent = element.parentInVisitor
if (element.transformByChildren || parent != null) {
println()
printVisitMethodDeclaration(
element = element,
override = true,
)
if (element.transformByChildren) {
printBlock {
println(element.visitorParameterName, ".transformChildren(this, data)")
println("return ", element.visitorParameterName)
}
} else {
println(" =")
withIndent {
println(parent!!.visitFunctionName, "(", element.visitorParameterName, ", data)")
}
}
}
}
}
}
fun printTransformer(generationPath: File, model: Model): GeneratedFile =
printVisitorCommon(generationPath, model, elementTransformerType) { printer, visitorType ->
TransformerPrinter(printer, visitorType, model.rootElement)
}
@@ -0,0 +1,142 @@
/*
* 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.ir.generator.print
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.*
import org.jetbrains.kotlin.ir.generator.IrTree
import org.jetbrains.kotlin.ir.generator.TREE_GENERATOR_README
import org.jetbrains.kotlin.ir.generator.elementTransformerType
import org.jetbrains.kotlin.ir.generator.elementTransformerVoidType
import org.jetbrains.kotlin.ir.generator.model.Element
import org.jetbrains.kotlin.ir.generator.model.Field
import org.jetbrains.kotlin.ir.generator.model.Model
import org.jetbrains.kotlin.utils.SmartPrinter
import org.jetbrains.kotlin.utils.withIndent
import java.io.File
private class TransformerVoidPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
) : AbstractVisitorPrinter<Element, Field>(printer) {
override val visitorTypeParameters: List<TypeVariable>
get() = emptyList()
override val visitorSuperType: ClassRef<PositionTypeParameterRef>
get() = elementTransformerType.withArgs(visitorDataType)
override val visitorDataType: TypeRef
get() = StandardTypes.nothing.copy(nullable = true)
// IrPackageFragment is treated as transformByChildren in IrElementTransformerVoid for historical reasons.
private val Element.isPackageFragment: Boolean
get() = this == IrTree.packageFragment
// Despite IrFile and IrExternalPackageFragment being transformByChildren, we treat them differently in IrElementTransformerVoid
// than in IrElementTransformer for historical reasons. We want to preserve the historical semantics here.
private val Element.isPackageFragmentChild: Boolean
get() = elementParents.any { it.element.isPackageFragment }
private val Element.transformByChildrenVoid: Boolean
get() = element.transformByChildren || isPackageFragment
override fun visitMethodReturnType(element: Element): Element =
when {
element.isPackageFragment -> element
element.transformByChildren -> element.getTransformExplicitType()
else -> element.parentInVisitor?.let(this::visitMethodReturnType) ?: element
}
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods() {
println()
val typeParameter = TypeVariable("T", listOf(IrTree.rootElement))
printFunctionWithBlockBody(
name = "transformPostfix",
parameters = listOf(FunctionParameter("body", Lambda(receiver = typeParameter, returnType = StandardTypes.unit))),
returnType = typeParameter,
typeParameters = listOf(typeParameter),
extensionReceiver = typeParameter,
visibility = Visibility.PROTECTED,
isInline = true,
) {
println("transformChildrenVoid()")
println("this.body()")
println("return this")
}
println()
printFunctionWithBlockBody(
name = "transformChildrenVoid",
parameters = emptyList(),
returnType = StandardTypes.unit,
extensionReceiver = IrTree.rootElement,
visibility = Visibility.PROTECTED,
) {
println("transformChildrenVoid(this@", visitorType.simpleName, ")")
}
}
context(ImportCollector)
override fun printMethodsForElement(element: Element) {
val parent = element.parentInVisitor
if (!element.transformByChildrenVoid && parent == null) return
printer.run {
println()
printVisitMethodDeclaration(element, hasDataParameter = false, modality = Modality.OPEN)
if (element.transformByChildrenVoid && !element.isPackageFragmentChild) {
printBlock {
println(element.visitorParameterName, ".transformChildren(this, null)")
println("return ", element.visitorParameterName)
}
} else {
println(" =")
withIndent {
print(parent!!.visitFunctionName, "(", element.visitorParameterName, ")")
if (element.isPackageFragmentChild) {
print(" as ", element.render())
}
println()
}
}
println()
printVisitMethodDeclaration(
element = element,
modality = Modality.FINAL,
override = true,
returnType = element.getTransformExplicitType(),
)
println(" =")
withIndent {
println(element.visitFunctionName, "(", element.visitorParameterName, ")")
}
}
}
}
fun printTransformerVoid(generationPath: File, model: Model): GeneratedFile =
printGeneratedType(
generationPath,
TREE_GENERATOR_README,
elementTransformerVoidType.packageName,
elementTransformerVoidType.simpleName,
) {
TransformerVoidPrinter(this, elementTransformerVoidType).printVisitor(model.elements)
println()
val transformerParameter = FunctionParameter("transformer", elementTransformerVoidType)
printFunctionWithBlockBody(
name = "transformChildrenVoid",
parameters = listOf(transformerParameter),
returnType = StandardTypes.unit,
extensionReceiver = IrTree.rootElement,
) {
println("transformChildren(", transformerParameter.name, ", null)")
}
}
@@ -0,0 +1,162 @@
/*
* 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.ir.generator.print
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.FunctionParameter
import org.jetbrains.kotlin.generators.tree.printer.GeneratedFile
import org.jetbrains.kotlin.generators.tree.printer.printBlock
import org.jetbrains.kotlin.generators.tree.printer.printFunctionDeclaration
import org.jetbrains.kotlin.ir.generator.IrTree
import org.jetbrains.kotlin.ir.generator.elementTransformerType
import org.jetbrains.kotlin.ir.generator.irTypeType
import org.jetbrains.kotlin.ir.generator.model.Element
import org.jetbrains.kotlin.ir.generator.model.Field
import org.jetbrains.kotlin.ir.generator.model.ListField
import org.jetbrains.kotlin.ir.generator.model.Model
import org.jetbrains.kotlin.ir.generator.model.SingleField
import org.jetbrains.kotlin.ir.generator.typeTransformerType
import org.jetbrains.kotlin.utils.SmartPrinter
import org.jetbrains.kotlin.utils.withIndent
import java.io.File
private class TypeTransformerPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
val rootElement: Element,
) : AbstractVisitorPrinter<Element, Field>(printer) {
override val visitorSuperType: ClassRef<PositionTypeParameterRef>
get() = elementTransformerType.withArgs(dataTypeVariable)
override val visitorTypeParameters: List<TypeVariable>
get() = listOf(dataTypeVariable)
override val visitorDataType: TypeRef
get() = dataTypeVariable
override fun visitMethodReturnType(element: Element) = element.getTransformExplicitType()
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
private fun Element.getFieldsWithIrTypeType(insideParent: Boolean = false): List<Field> {
val parentsFields = elementParents.flatMap { it.element.getFieldsWithIrTypeType(insideParent = true) }
if (insideParent && this.parentInVisitor != null) {
return parentsFields
}
val irTypeFields = this.fields
.filter {
val type = when (it) {
is SingleField -> it.typeRef
is ListField -> it.baseType
}
type.toString() == irTypeType.toString()
}
return irTypeFields + parentsFields
}
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods() {
val typeTP = TypeVariable("Type", listOf(irTypeType.copy(nullable = true)))
printFunctionDeclaration(
name = "transformType",
parameters = listOf(
FunctionParameter("container", rootElement),
FunctionParameter("type", typeTP),
FunctionParameter("data", visitorDataType)
),
returnType = typeTP,
typeParameters = listOf(typeTP),
)
println()
}
context(ImportCollector)
override fun printMethodsForElement(element: Element) {
val irTypeFields = element.getFieldsWithIrTypeType()
if (irTypeFields.isEmpty()) return
if (element.parentInVisitor == null) return
printer.run {
println()
val visitorParam = element.visitorParameterName
printVisitMethodDeclaration(
element = element,
override = true,
)
fun addVisitTypeStatement(field: Field) {
val access = "$visitorParam.${field.name}"
when (field) {
is SingleField -> println(access, " = ", "transformType(", visitorParam, ", ", access, ", data)")
is ListField -> {
if (field.isMutable) {
println(access, " = ", access, ".map { transformType(", visitorParam, ", it, data) }")
} else {
println("for (i in 0 until ", access, ".size) {")
withIndent {
println(access, "[i] = transformType(", visitorParam, ", ", access, "[i], data)")
}
println("}")
}
}
}
}
printBlock {
when (element) {
IrTree.memberAccessExpression -> {
if (irTypeFields.singleOrNull()?.name != "typeArguments") {
error(
"""`${IrTree.memberAccessExpression.typeName}` has unexpected fields with `IrType` type.
|Please adjust logic of `${visitorType.simpleName}`'s generation.""".trimMargin()
)
}
println("(0 until ", visitorParam, ".typeArgumentsCount).forEach {")
withIndent {
println(visitorParam, ".getTypeArgument(it)?.let { type ->")
withIndent {
println(
visitorParam,
".putTypeArgument(it, transformType(",
visitorParam,
", type, data))"
)
}
println("}")
}
println("}")
}
IrTree.`class` -> {
println(visitorParam, ".valueClassRepresentation?.mapUnderlyingType {")
withIndent {
println("transformType(", visitorParam, ", it, data)")
}
println("}")
irTypeFields.forEach(::addVisitTypeStatement)
}
else -> {
irTypeFields.forEach(::addVisitTypeStatement)
}
}
println(
"return super.",
element.visitFunctionName,
"(",
visitorParam,
", data)"
)
}
}
}
}
fun printTypeVisitor(generationPath: File, model: Model): GeneratedFile =
printVisitorCommon(generationPath, model, typeTransformerType) { printer, visitorType ->
TypeTransformerPrinter(printer, visitorType, model.rootElement)
}
@@ -5,27 +5,13 @@
package org.jetbrains.kotlin.ir.generator.print
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.*
import org.jetbrains.kotlin.ir.generator.*
import org.jetbrains.kotlin.ir.generator.model.*
import org.jetbrains.kotlin.ir.generator.model.ListField
import org.jetbrains.kotlin.ir.generator.model.Model
import org.jetbrains.kotlin.utils.SmartPrinter
import org.jetbrains.kotlin.utils.withIndent
import java.io.File
private fun printVisitorCommon(
generationPath: File,
model: Model,
visitorType: ClassRef<*>,
makePrinter: (SmartPrinter, ClassRef<*>) -> AbstractVisitorPrinter<Element, Field>,
): GeneratedFile =
printGeneratedType(generationPath, TREE_GENERATOR_README, visitorType.packageName, visitorType.simpleName) {
makePrinter(this, visitorType).printVisitor(model.elements)
}
private open class VisitorPrinter(printer: SmartPrinter, override val visitorType: ClassRef<*>) :
AbstractVisitorPrinter<Element, Field>(printer) {
@@ -46,344 +32,3 @@ private open class VisitorPrinter(printer: SmartPrinter, override val visitorTyp
fun printVisitor(generationPath: File, model: Model) = printVisitorCommon(generationPath, model, elementVisitorType, ::VisitorPrinter)
private class VisitorVoidPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
) : AbstractVisitorVoidPrinter<Element, Field>(printer) {
override val visitorSuperClass: ClassRef<PositionTypeParameterRef>
get() = elementVisitorType
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
override val useAbstractMethodForRootElement: Boolean
get() = false
override val overriddenVisitMethodsAreFinal: Boolean
get() = false
}
fun printVisitorVoid(generationPath: File, model: Model) =
printVisitorCommon(generationPath, model, elementVisitorVoidType, ::VisitorVoidPrinter)
private class TransformerPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
val rootElement: Element,
) : AbstractVisitorPrinter<Element, Field>(printer) {
override val visitorSuperType: ClassRef<PositionTypeParameterRef>
get() = elementVisitorType.withArgs(rootElement, dataTypeVariable)
override val visitorTypeParameters: List<TypeVariable>
get() = listOf(dataTypeVariable)
override val visitorDataType: TypeRef
get() = dataTypeVariable
override fun visitMethodReturnType(element: Element) = element.getTransformExplicitType()
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
context(ImportCollector)
override fun printMethodsForElement(element: Element) {
printer.run {
val parent = element.parentInVisitor
if (element.transformByChildren || parent != null) {
println()
printVisitMethodDeclaration(
element = element,
override = true,
)
if (element.transformByChildren) {
printBlock {
println(element.visitorParameterName, ".transformChildren(this, data)")
println("return ", element.visitorParameterName)
}
} else {
println(" =")
withIndent {
println(parent!!.visitFunctionName, "(", element.visitorParameterName, ", data)")
}
}
}
}
}
}
fun printTransformer(generationPath: File, model: Model): GeneratedFile =
printVisitorCommon(generationPath, model, elementTransformerType) { printer, visitorType ->
TransformerPrinter(printer, visitorType, model.rootElement)
}
private class TransformerVoidPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
) : AbstractVisitorPrinter<Element, Field>(printer) {
override val visitorTypeParameters: List<TypeVariable>
get() = emptyList()
override val visitorSuperType: ClassRef<PositionTypeParameterRef>
get() = elementTransformerType.withArgs(visitorDataType)
override val visitorDataType: TypeRef
get() = StandardTypes.nothing.copy(nullable = true)
// IrPackageFragment is treated as transformByChildren in IrElementTransformerVoid for historical reasons.
private val Element.isPackageFragment: Boolean
get() = this == IrTree.packageFragment
// Despite IrFile and IrExternalPackageFragment being transformByChildren, we treat them differently in IrElementTransformerVoid
// than in IrElementTransformer for historical reasons. We want to preserve the historical semantics here.
private val Element.isPackageFragmentChild: Boolean
get() = elementParents.any { it.element.isPackageFragment }
private val Element.transformByChildrenVoid: Boolean
get() = element.transformByChildren || isPackageFragment
override fun visitMethodReturnType(element: Element): Element =
when {
element.isPackageFragment -> element
element.transformByChildren -> element.getTransformExplicitType()
else -> element.parentInVisitor?.let(this::visitMethodReturnType) ?: element
}
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods() {
println()
val typeParameter = TypeVariable("T", listOf(IrTree.rootElement))
printFunctionWithBlockBody(
name = "transformPostfix",
parameters = listOf(FunctionParameter("body", Lambda(receiver = typeParameter, returnType = StandardTypes.unit))),
returnType = typeParameter,
typeParameters = listOf(typeParameter),
extensionReceiver = typeParameter,
visibility = Visibility.PROTECTED,
isInline = true,
) {
println("transformChildrenVoid()")
println("this.body()")
println("return this")
}
println()
printFunctionWithBlockBody(
name = "transformChildrenVoid",
parameters = emptyList(),
returnType = StandardTypes.unit,
extensionReceiver = IrTree.rootElement,
visibility = Visibility.PROTECTED,
) {
println("transformChildrenVoid(this@", visitorType.simpleName, ")")
}
}
context(ImportCollector)
override fun printMethodsForElement(element: Element) {
val parent = element.parentInVisitor
if (!element.transformByChildrenVoid && parent == null) return
printer.run {
println()
printVisitMethodDeclaration(element, hasDataParameter = false, modality = Modality.OPEN)
if (element.transformByChildrenVoid && !element.isPackageFragmentChild) {
printBlock {
println(element.visitorParameterName, ".transformChildren(this, null)")
println("return ", element.visitorParameterName)
}
} else {
println(" =")
withIndent {
print(parent!!.visitFunctionName, "(", element.visitorParameterName, ")")
if (element.isPackageFragmentChild) {
print(" as ", element.render())
}
println()
}
}
println()
printVisitMethodDeclaration(
element = element,
modality = Modality.FINAL,
override = true,
returnType = element.getTransformExplicitType(),
)
println(" =")
withIndent {
println(element.visitFunctionName, "(", element.visitorParameterName, ")")
}
}
}
}
fun printTransformerVoid(generationPath: File, model: Model): GeneratedFile =
printGeneratedType(
generationPath,
TREE_GENERATOR_README,
elementTransformerVoidType.packageName,
elementTransformerVoidType.simpleName,
) {
TransformerVoidPrinter(this, elementTransformerVoidType).printVisitor(model.elements)
println()
val transformerParameter = FunctionParameter("transformer", elementTransformerVoidType)
printFunctionWithBlockBody(
name = "transformChildrenVoid",
parameters = listOf(transformerParameter),
returnType = StandardTypes.unit,
extensionReceiver = IrTree.rootElement,
) {
println("transformChildren(", transformerParameter.name, ", null)")
}
}
private class TypeTransformerPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
val rootElement: Element,
) : AbstractVisitorPrinter<Element, Field>(printer) {
override val visitorSuperType: ClassRef<PositionTypeParameterRef>
get() = elementTransformerType.withArgs(dataTypeVariable)
override val visitorTypeParameters: List<TypeVariable>
get() = listOf(dataTypeVariable)
override val visitorDataType: TypeRef
get() = dataTypeVariable
override fun visitMethodReturnType(element: Element) = element.getTransformExplicitType()
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
private fun Element.getFieldsWithIrTypeType(insideParent: Boolean = false): List<Field> {
val parentsFields = elementParents.flatMap { it.element.getFieldsWithIrTypeType(insideParent = true) }
if (insideParent && this.parentInVisitor != null) {
return parentsFields
}
val irTypeFields = this.fields
.filter {
val type = when (it) {
is SingleField -> it.typeRef
is ListField -> it.baseType
}
type.toString() == irTypeType.toString()
}
return irTypeFields + parentsFields
}
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods() {
val typeTP = TypeVariable("Type", listOf(irTypeType.copy(nullable = true)))
printFunctionDeclaration(
name = "transformType",
parameters = listOf(
FunctionParameter("container", rootElement),
FunctionParameter("type", typeTP),
FunctionParameter("data", visitorDataType)
),
returnType = typeTP,
typeParameters = listOf(typeTP),
)
println()
}
context(ImportCollector)
override fun printMethodsForElement(element: Element) {
val irTypeFields = element.getFieldsWithIrTypeType()
if (irTypeFields.isEmpty()) return
if (element.parentInVisitor == null) return
printer.run {
println()
val visitorParam = element.visitorParameterName
printVisitMethodDeclaration(
element = element,
override = true,
)
fun addVisitTypeStatement(field: Field) {
val access = "$visitorParam.${field.name}"
when (field) {
is SingleField -> println(access, " = ", "transformType(", visitorParam, ", ", access, ", data)")
is ListField -> {
if (field.isMutable) {
println(access, " = ", access, ".map { transformType(", visitorParam, ", it, data) }")
} else {
println("for (i in 0 until ", access, ".size) {")
withIndent {
println(access, "[i] = transformType(", visitorParam, ", ", access, "[i], data)")
}
println("}")
}
}
}
}
printBlock {
when (element) {
IrTree.memberAccessExpression -> {
if (irTypeFields.singleOrNull()?.name != "typeArguments") {
error(
"""`${IrTree.memberAccessExpression.typeName}` has unexpected fields with `IrType` type.
|Please adjust logic of `${visitorType.simpleName}`'s generation.""".trimMargin()
)
}
println("(0 until ", visitorParam, ".typeArgumentsCount).forEach {")
withIndent {
println(visitorParam, ".getTypeArgument(it)?.let { type ->")
withIndent {
println(
visitorParam,
".putTypeArgument(it, transformType(",
visitorParam,
", type, data))"
)
}
println("}")
}
println("}")
}
IrTree.`class` -> {
println(visitorParam, ".valueClassRepresentation?.mapUnderlyingType {")
withIndent {
println("transformType(", visitorParam, ", it, data)")
}
println("}")
irTypeFields.forEach(::addVisitTypeStatement)
}
else -> {
irTypeFields.forEach(::addVisitTypeStatement)
}
}
println(
"return super.",
element.visitFunctionName,
"(",
visitorParam,
", data)"
)
}
}
}
}
fun printTypeVisitor(generationPath: File, model: Model): GeneratedFile =
printVisitorCommon(generationPath, model, typeTransformerType) { printer, visitorType ->
TypeTransformerPrinter(printer, visitorType, model.rootElement)
}
private fun Element.getTransformExplicitType(): Element {
return generateSequence(this) { it.parentInVisitor }
.firstNotNullOfOrNull {
when {
it.transformByChildren -> it.transformerReturnType ?: it
else -> it.transformerReturnType
}
} ?: this
}
@@ -0,0 +1,38 @@
/*
* 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.ir.generator.print
import org.jetbrains.kotlin.generators.tree.AbstractVisitorVoidPrinter
import org.jetbrains.kotlin.generators.tree.ClassRef
import org.jetbrains.kotlin.generators.tree.PositionTypeParameterRef
import org.jetbrains.kotlin.ir.generator.elementVisitorType
import org.jetbrains.kotlin.ir.generator.elementVisitorVoidType
import org.jetbrains.kotlin.ir.generator.model.Element
import org.jetbrains.kotlin.ir.generator.model.Field
import org.jetbrains.kotlin.ir.generator.model.Model
import org.jetbrains.kotlin.utils.SmartPrinter
import java.io.File
private class VisitorVoidPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
) : AbstractVisitorVoidPrinter<Element, Field>(printer) {
override val visitorSuperClass: ClassRef<PositionTypeParameterRef>
get() = elementVisitorType
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
override val useAbstractMethodForRootElement: Boolean
get() = false
override val overriddenVisitMethodsAreFinal: Boolean
get() = false
}
fun printVisitorVoid(generationPath: File, model: Model) =
printVisitorCommon(generationPath, model, elementVisitorVoidType, ::VisitorVoidPrinter)
@@ -0,0 +1,37 @@
/*
* 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.ir.generator.print
import org.jetbrains.kotlin.generators.tree.AbstractVisitorPrinter
import org.jetbrains.kotlin.generators.tree.ClassRef
import org.jetbrains.kotlin.generators.tree.printer.GeneratedFile
import org.jetbrains.kotlin.generators.tree.printer.printGeneratedType
import org.jetbrains.kotlin.ir.generator.TREE_GENERATOR_README
import org.jetbrains.kotlin.ir.generator.model.Element
import org.jetbrains.kotlin.ir.generator.model.Field
import org.jetbrains.kotlin.ir.generator.model.Model
import org.jetbrains.kotlin.utils.SmartPrinter
import java.io.File
internal fun printVisitorCommon(
generationPath: File,
model: Model,
visitorType: ClassRef<*>,
makePrinter: (SmartPrinter, ClassRef<*>) -> AbstractVisitorPrinter<Element, Field>,
): GeneratedFile =
printGeneratedType(generationPath, TREE_GENERATOR_README, visitorType.packageName, visitorType.simpleName) {
makePrinter(this, visitorType).printVisitor(model.elements)
}
internal fun Element.getTransformExplicitType(): Element {
return generateSequence(this) { it.parentInVisitor }
.firstNotNullOfOrNull {
when {
it.transformByChildren -> it.transformerReturnType ?: it
else -> it.transformerReturnType
}
} ?: this
}