[IR] Add kdoc for IrElement
This commit is contained in:
committed by
Space Team
parent
ba5ff7967c
commit
de7de7b287
@@ -12,20 +12,75 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
/**
|
||||
* A non-leaf IR tree element.
|
||||
* The root interface of the IR tree. Each IR node implements this interface.
|
||||
*
|
||||
* Generated from: [org.jetbrains.kotlin.ir.generator.IrTree.rootElement]
|
||||
*/
|
||||
interface IrElement {
|
||||
/**
|
||||
* The start offset of the syntax node from which this IR node was generated,
|
||||
* in number of characters from the start of the source file. If there is no source information
|
||||
* for this IR node,
|
||||
* the [UNDEFINED_OFFSET] constant is used. In order to get the line number and the column
|
||||
* number from this offset,
|
||||
* [IrFileEntry.getLineNumber] and [IrFileEntry.getColumnNumber] can be used.
|
||||
*
|
||||
* @see IrFileEntry.getSourceRangeInfo
|
||||
*/
|
||||
val startOffset: Int
|
||||
|
||||
/**
|
||||
* The end offset of the syntax node from which this IR node was generated,
|
||||
* in number of characters from the start of the source file. If there is no source information
|
||||
* for this IR node,
|
||||
* the [UNDEFINED_OFFSET] constant is used. In order to get the line number and the column
|
||||
* number from this offset,
|
||||
* [IrFileEntry.getLineNumber] and [IrFileEntry.getColumnNumber] can be used.
|
||||
*
|
||||
* @see IrFileEntry.getSourceRangeInfo
|
||||
*/
|
||||
val endOffset: Int
|
||||
|
||||
/**
|
||||
* Runs the provided [visitor] on the IR subtree with the root at this node.
|
||||
*
|
||||
* @param visitor The visitor to accept.
|
||||
* @param data An arbitrary context to pass to each invocation of [visitor]'s methods.
|
||||
* @return The value returned by the topmost `visit*` invocation.
|
||||
*/
|
||||
fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R
|
||||
|
||||
/**
|
||||
* Runs the provided [transformer] on the IR subtree with the root at this node.
|
||||
*
|
||||
* @param transformer The transformer to use.
|
||||
* @param data An arbitrary context to pass to each invocation of [transformer]'s methods.
|
||||
* @return The transformed node.
|
||||
*/
|
||||
fun <D> transform(transformer: IrElementTransformer<D>, data: D): IrElement
|
||||
|
||||
/**
|
||||
* Runs the provided [visitor] on subtrees with roots in this node's children.
|
||||
*
|
||||
* Basically, calls `accept(visitor, data)` on each child of this node.
|
||||
*
|
||||
* Does **not** run [visitor] on this node itself.
|
||||
*
|
||||
* @param visitor The visitor for children to accept.
|
||||
* @param data An arbitrary context to pass to each invocation of [visitor]'s methods.
|
||||
*/
|
||||
fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D)
|
||||
|
||||
/**
|
||||
* Recursively transforms this node's children *in place* using [transformer].
|
||||
*
|
||||
* Basically, executes `this.child = this.child.transform(transformer, data)` for each child
|
||||
* of this node.
|
||||
*
|
||||
* Does **not** run [transformer] on this node itself.
|
||||
*
|
||||
* @param transformer The transformer to use for transforming the children.
|
||||
* @param data An arbitrary context to pass to each invocation of [transformer]'s methods.
|
||||
*/
|
||||
fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D)
|
||||
}
|
||||
|
||||
@@ -42,8 +42,21 @@ object IrTree : AbstractTreeBuilder() {
|
||||
transform = true
|
||||
transformByChildren = true
|
||||
|
||||
+field("startOffset", int, mutable = false)
|
||||
+field("endOffset", int, mutable = false)
|
||||
fun offsetField(prefix: String) = field(prefix + "Offset", int, mutable = false) {
|
||||
kdoc = """
|
||||
The $prefix offset of the syntax node from which this IR node was generated,
|
||||
in number of characters from the start of the source file. If there is no source information for this IR node,
|
||||
the [UNDEFINED_OFFSET] constant is used. In order to get the line number and the column number from this offset,
|
||||
[IrFileEntry.getLineNumber] and [IrFileEntry.getColumnNumber] can be used.
|
||||
|
||||
@see IrFileEntry.getSourceRangeInfo
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
+offsetField("start")
|
||||
+offsetField("end")
|
||||
|
||||
kDoc = "The root interface of the IR tree. Each IR node implements this interface."
|
||||
}
|
||||
val statement: ElementConfig by element(Other)
|
||||
|
||||
|
||||
+105
-22
@@ -76,32 +76,68 @@ fun printElements(generationPath: File, model: Model) = sequence {
|
||||
}
|
||||
|
||||
val isRootElement = element.elementParents.isEmpty()
|
||||
val acceptMethodName = "accept"
|
||||
val transformMethodName = "transform"
|
||||
if (element.accept) {
|
||||
addFunction(FunSpec.builder("accept").apply {
|
||||
addFunction(FunSpec.builder(acceptMethodName).apply {
|
||||
addModifiers(if (isRootElement) KModifier.ABSTRACT else KModifier.OVERRIDE)
|
||||
val r = TypeVariableName("R")
|
||||
val d = TypeVariableName("D")
|
||||
addTypeVariable(r)
|
||||
addTypeVariable(d)
|
||||
addParameter("visitor", elementVisitorType.toPoet().tryParameterizedBy(r, d))
|
||||
addParameter("data", d)
|
||||
val visitorParam = ParameterSpec.builder("visitor", elementVisitorType.toPoet().tryParameterizedBy(r, d))
|
||||
.build()
|
||||
.also(::addParameter)
|
||||
val dataParam = ParameterSpec.builder("data", d)
|
||||
.build()
|
||||
.also(::addParameter)
|
||||
returns(r)
|
||||
if (!isRootElement) {
|
||||
addStatement("return visitor.${element.visitFunName}(this, data)")
|
||||
addStatement("return %N.%N(this, %N)", visitorParam, element.visitFunName, dataParam)
|
||||
}
|
||||
if (isRootElement) {
|
||||
addKdoc(
|
||||
"""
|
||||
Runs the provided [%1N] on the IR subtree with the root at this node.
|
||||
|
||||
@param %1N The visitor to accept.
|
||||
@param %2N An arbitrary context to pass to each invocation of [%1N]'s methods.
|
||||
@return The value returned by the topmost `visit*` invocation.
|
||||
""".trimIndent(),
|
||||
visitorParam,
|
||||
dataParam,
|
||||
)
|
||||
}
|
||||
}.build())
|
||||
}
|
||||
|
||||
if (element.transform) {
|
||||
addFunction(FunSpec.builder("transform").apply {
|
||||
addFunction(FunSpec.builder(transformMethodName).apply {
|
||||
addModifiers(if (isRootElement) KModifier.ABSTRACT else KModifier.OVERRIDE)
|
||||
val d = TypeVariableName("D")
|
||||
addTypeVariable(d)
|
||||
addParameter("transformer", elementTransformerType.toPoet().tryParameterizedBy(d))
|
||||
addParameter("data", d)
|
||||
val transformerParam = ParameterSpec.builder("transformer", elementTransformerType.toPoet().tryParameterizedBy(d))
|
||||
.build()
|
||||
.also(::addParameter)
|
||||
val dataParam = ParameterSpec.builder("data", d)
|
||||
.build()
|
||||
.also(::addParameter)
|
||||
returns(selfParametrizedElementName)
|
||||
if (!isRootElement) {
|
||||
addStatement("return accept(transformer, data) as %T", selfParametrizedElementName)
|
||||
addStatement("return %N(%N, %N) as %T", acceptMethodName, transformerParam, dataParam, selfParametrizedElementName)
|
||||
}
|
||||
if (isRootElement) {
|
||||
addKdoc(
|
||||
"""
|
||||
Runs the provided [%1N] on the IR subtree with the root at this node.
|
||||
|
||||
@param %1N The transformer to use.
|
||||
@param %2N An arbitrary context to pass to each invocation of [%1N]'s methods.
|
||||
@return The transformed node.
|
||||
""".trimIndent(),
|
||||
transformerParam,
|
||||
dataParam,
|
||||
)
|
||||
}
|
||||
}.build())
|
||||
}
|
||||
@@ -111,18 +147,41 @@ fun printElements(generationPath: File, model: Model) = sequence {
|
||||
addModifiers(if (isRootElement) KModifier.ABSTRACT else KModifier.OVERRIDE)
|
||||
val d = TypeVariableName("D")
|
||||
addTypeVariable(d)
|
||||
addParameter("visitor", elementVisitorType.toPoet().tryParameterizedBy(UNIT, d))
|
||||
addParameter("data", d)
|
||||
|
||||
val visitorParam = ParameterSpec
|
||||
.builder("visitor", elementVisitorType.toPoet().tryParameterizedBy(UNIT, d)).build()
|
||||
.also(::addParameter)
|
||||
val dataParam = ParameterSpec
|
||||
.builder("data", d).build()
|
||||
.also(::addParameter)
|
||||
|
||||
for (child in element.walkableChildren) {
|
||||
addStatement(buildString {
|
||||
append(child.name)
|
||||
append("%N")
|
||||
if (child.nullable) append("?")
|
||||
when (child) {
|
||||
is SingleField -> append(".accept(visitor, data)")
|
||||
is ListField -> append(".forEach { it.accept(visitor, data) }")
|
||||
is SingleField -> append(".%N(%N, %N)")
|
||||
is ListField -> append(".forEach { it.%N(%N, %N) }")
|
||||
}
|
||||
})
|
||||
}, child.name, acceptMethodName, visitorParam, dataParam)
|
||||
}
|
||||
|
||||
if (isRootElement) {
|
||||
addKdoc(
|
||||
"""
|
||||
Runs the provided [%1N] on subtrees with roots in this node's children.
|
||||
|
||||
Basically, calls `%3N(%1N, %2N)` on each child of this node.
|
||||
|
||||
Does **not** run [%1N] on this node itself.
|
||||
|
||||
@param %1N The visitor for children to accept.
|
||||
@param %2N An arbitrary context to pass to each invocation of [%1N]'s methods.
|
||||
""".trimIndent(),
|
||||
visitorParam,
|
||||
dataParam,
|
||||
acceptMethodName,
|
||||
)
|
||||
}
|
||||
}.build())
|
||||
}
|
||||
@@ -132,32 +191,38 @@ fun printElements(generationPath: File, model: Model) = sequence {
|
||||
addModifiers(if (isRootElement) KModifier.ABSTRACT else KModifier.OVERRIDE)
|
||||
val d = TypeVariableName("D")
|
||||
addTypeVariable(d)
|
||||
addParameter("transformer", elementTransformerType.toPoet().tryParameterizedBy(d))
|
||||
addParameter("data", d)
|
||||
val transformerParam =
|
||||
ParameterSpec.builder("transformer", elementTransformerType.toPoet().tryParameterizedBy(d)).build()
|
||||
.also(::addParameter)
|
||||
val dataParam = ParameterSpec.builder("data", d).build().also(::addParameter)
|
||||
|
||||
for (child in element.transformableChildren) {
|
||||
val args = mutableListOf<Any>()
|
||||
val code = buildString {
|
||||
append("%N")
|
||||
args.add(child.name)
|
||||
when (child) {
|
||||
is SingleField -> {
|
||||
append(child.name)
|
||||
append(" = ")
|
||||
append(child.name)
|
||||
append(" = %N")
|
||||
args.add(child.name)
|
||||
if (child.nullable) append("?")
|
||||
append(".transform(transformer, data)")
|
||||
append(".%N(%N, %N)")
|
||||
args.add(transformMethodName)
|
||||
}
|
||||
is ListField -> {
|
||||
append(child.name)
|
||||
if (child.mutable) {
|
||||
append(" = ")
|
||||
append(child.name)
|
||||
if (child.nullable) append("?")
|
||||
}
|
||||
append(".%M(transformer, data)")
|
||||
append(".%M(%N, %N)")
|
||||
args.add(if (child.mutable) transformIfNeeded else transformInPlace)
|
||||
}
|
||||
}
|
||||
|
||||
args.add(transformerParam)
|
||||
args.add(dataParam)
|
||||
|
||||
if (child is SingleField) {
|
||||
val elRef = child.type as ElementRef
|
||||
if (!elRef.element.transform) {
|
||||
@@ -170,6 +235,24 @@ fun printElements(generationPath: File, model: Model) = sequence {
|
||||
|
||||
addStatement(code, *args.toTypedArray())
|
||||
}
|
||||
|
||||
if (isRootElement) {
|
||||
addKdoc(
|
||||
"""
|
||||
Recursively transforms this node's children *in place* using [%1N].
|
||||
|
||||
Basically, executes `this.child = this.child.%3N(%1N, %2N)` for each child of this node.
|
||||
|
||||
Does **not** run [%1N] on this node itself.
|
||||
|
||||
@param %1N The transformer to use for transforming the children.
|
||||
@param %2N An arbitrary context to pass to each invocation of [%1N]'s methods.
|
||||
""".trimIndent(),
|
||||
transformerParam,
|
||||
dataParam,
|
||||
transformMethodName,
|
||||
)
|
||||
}
|
||||
}.build())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user