[IR generator] Auto-generate IrElementTransformerVoid
This commit is contained in:
committed by
Space Team
parent
6798ff4a73
commit
18ed85c26e
+1
@@ -31,6 +31,7 @@ val statementOriginType = type(exprs, "IrStatementOrigin")
|
||||
val elementVisitorType = type(visitors, "IrElementVisitor")
|
||||
val elementVisitorVoidType = type(visitors, "IrElementVisitorVoid")
|
||||
val elementTransformerType = type(visitors, "IrElementTransformer")
|
||||
val elementTransformerVoidType = type(visitors, "IrElementTransformerVoid", TypeKind.Class)
|
||||
val typeTransformerType = type(visitors, "IrTypeTransformer")
|
||||
val mutableAnnotationContainerType = type(declarations, "IrMutableAnnotationContainer")
|
||||
val irTypeType = type(types, "IrType")
|
||||
|
||||
@@ -29,8 +29,8 @@ fun main(args: Array<String>) {
|
||||
yield(printVisitor(generationPath, model))
|
||||
yield(printVisitorVoid(generationPath, model))
|
||||
yield(printTransformer(generationPath, model))
|
||||
yield(printTransformerVoid(generationPath, model))
|
||||
yield(printTypeVisitor(generationPath, model))
|
||||
// IrElementTransformerVoid is too random to autogenerate
|
||||
yield(printFactory(generationPath, model))
|
||||
}.map {
|
||||
GeneratorsFileUtil.writeFileIfContentChanged(it.file, it.newText, logNotChanged = false)
|
||||
|
||||
+139
-3
@@ -5,11 +5,14 @@
|
||||
|
||||
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.generators.tree.printer.FunctionParameter
|
||||
import org.jetbrains.kotlin.generators.tree.printer.GeneratedFile
|
||||
import org.jetbrains.kotlin.generators.tree.printer.printFunctionDeclaration
|
||||
import org.jetbrains.kotlin.generators.tree.printer.printGeneratedType
|
||||
import org.jetbrains.kotlin.ir.generator.*
|
||||
import org.jetbrains.kotlin.ir.generator.model.*
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||
import org.jetbrains.kotlin.utils.SmartPrinter
|
||||
import org.jetbrains.kotlin.utils.withIndent
|
||||
@@ -119,6 +122,139 @@ fun printTransformer(generationPath: File, model: Model): GeneratedFile =
|
||||
TransformerPrinter(printer, visitorType, model.rootElement)
|
||||
}
|
||||
|
||||
private class TransformerVoidPrinter(
|
||||
printer: SmartPrinter,
|
||||
override val visitorType: ClassRef<*>,
|
||||
) : AbstractVisitorPrinter<Element, Field>(printer, visitSuperTypeByDefault = false) {
|
||||
|
||||
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() = name == IrTree.packageFragment.name
|
||||
|
||||
// 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))
|
||||
printFunctionDeclaration(
|
||||
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(" {")
|
||||
withIndent {
|
||||
println("transformChildrenVoid()")
|
||||
println("this.body()")
|
||||
println("return this")
|
||||
}
|
||||
println("}")
|
||||
println()
|
||||
printFunctionDeclaration(
|
||||
name = "transformChildrenVoid",
|
||||
parameters = emptyList(),
|
||||
returnType = StandardTypes.unit,
|
||||
extensionReceiver = IrTree.rootElement,
|
||||
visibility = Visibility.PROTECTED,
|
||||
)
|
||||
println(" {")
|
||||
withIndent {
|
||||
println("transformChildrenVoid(this@", visitorType.simpleName, ")")
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
|
||||
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) {
|
||||
println(" {")
|
||||
withIndent {
|
||||
println(element.visitorParameterName, ".transformChildren(this, null)")
|
||||
println("return ", element.visitorParameterName)
|
||||
}
|
||||
println("}")
|
||||
} 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)
|
||||
printFunctionDeclaration(
|
||||
name = "transformChildrenVoid",
|
||||
parameters = listOf(transformerParameter),
|
||||
returnType = StandardTypes.unit,
|
||||
extensionReceiver = IrTree.rootElement,
|
||||
)
|
||||
println(" {")
|
||||
withIndent {
|
||||
println("transformChildren(", transformerParameter.name, ", null)")
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
|
||||
private class TypeTransformerPrinter(
|
||||
printer: SmartPrinter,
|
||||
override val visitorType: ClassRef<*>,
|
||||
@@ -260,7 +396,7 @@ fun printTypeVisitor(generationPath: File, model: Model): GeneratedFile =
|
||||
}
|
||||
|
||||
private fun Element.getTransformExplicitType(): Element {
|
||||
return generateSequence(this) { it.parentInVisitor?.element }
|
||||
return generateSequence(this) { it.parentInVisitor }
|
||||
.firstNotNullOfOrNull {
|
||||
when {
|
||||
it.transformByChildren -> it.transformerReturnType ?: it
|
||||
|
||||
Reference in New Issue
Block a user