[IR] KotlinLikeDumper: better support for calls and annotations

* IrCall
* IrConstructorCall
* IrDelegatingConstructorCall
* print arguments for annotations
This commit is contained in:
Zalim Bashorov
2020-11-06 01:47:24 +03:00
committed by teamcityserver
parent fc5c674c60
commit ef2adfa835
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -263,11 +264,8 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
private fun IrConstructorCall.printAnAnnotationWithNoIndent(prefix: String = "") { private fun IrConstructorCall.printAnAnnotationWithNoIndent(prefix: String = "") {
val clazz = symbol.owner.parentAsClass p.printWithNoIndent("@" + (if (prefix.isEmpty()) "" else "$prefix:"))
assert(clazz.isAnnotationClass) visitConstructorCall(this)
// TODO render arguments / reuse visitCall or visitConstructorCall
p.printWithNoIndent("@" + (if (prefix.isEmpty()) "" else "$prefix:") + clazz.name.asString())
if (valueArgumentsCount > 0) p.printWithNoIndent("(...)")
} }
private fun IrAnnotationContainer.printlnAnnotations(prefix: String = "") { private fun IrAnnotationContainer.printlnAnnotations(prefix: String = "") {
@@ -818,50 +816,101 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
override fun visitCall(expression: IrCall) { override fun visitCall(expression: IrCall) {
val declaration = expression.symbol.owner // TODO process specially builtin symbols
expression.printIrFunctionAccessExpressionWithNoIndent(
expression.symbol.owner.name,
superQualifierSymbol = expression.superQualifierSymbol,
omitBracesIfNoArguments = false
)
}
expression.dispatchReceiver?.let { override fun visitConstructorCall(expression: IrConstructorCall) {
it.acceptVoid(this) // TODO could constructors have receiver?
val clazz = expression.symbol.owner.parentAsClass
expression.printIrFunctionAccessExpressionWithNoIndent(
clazz.name,
superQualifierSymbol = null,
omitBracesIfNoArguments = clazz.isAnnotationClass
)
}
private fun IrFunctionAccessExpression.printIrFunctionAccessExpressionWithNoIndent(
name: Name,
superQualifierSymbol: IrClassSymbol?,
omitBracesIfNoArguments: Boolean
) {
// TODO origin
val twoReceivers =
(dispatchReceiver != null || superQualifierSymbol != null) && extensionReceiver != null
if (twoReceivers) {
p.printWithNoIndent("(")
}
superQualifierSymbol?.let {
// TODO should we print super classifier somehow?
p.printWithNoIndent("super")
}
dispatchReceiver?.let {
if (superQualifierSymbol == null) it.acceptVoid(this@KotlinLikeDumper)
// else assert dispatchReceiver === this
}
if (twoReceivers) {
p.printWithNoIndent(", ")
}
extensionReceiver?.acceptVoid(this@KotlinLikeDumper)
if (twoReceivers) {
p.printWithNoIndent(")")
}
if (dispatchReceiver != null || extensionReceiver != null || superQualifierSymbol != null) {
p.printWithNoIndent(".") p.printWithNoIndent(".")
} }
p.printWithNoIndent(declaration.name.asString()) // what if it's unbound
val declaration = symbol.owner
if (expression.typeArgumentsCount > 0) { p.printWithNoIndent(name.asString())
if (typeArgumentsCount > 0) {
p.printWithNoIndent("<") p.printWithNoIndent("<")
repeat(expression.typeArgumentsCount) { repeat(typeArgumentsCount) {
if (it > 0) { if (it > 0) {
p.printWithNoIndent(", ") p.printWithNoIndent(", ")
} }
expression.getTypeArgument(it)!!.printTypeWithNoIndent() // TODO flag to print type param name?
getTypeArgument(it)!!.printTypeWithNoIndent()
} }
p.printWithNoIndent(">") p.printWithNoIndent(">")
} }
p.printWithNoIndent("(") if (omitBracesIfNoArguments && valueArgumentsCount == 0 && typeArgumentsCount == 0) return
expression.extensionReceiver?.let {
// TODO
p.printWithNoIndent("\$receiver = ")
it.acceptVoid(this)
if (expression.valueArgumentsCount > 0) p.printWithNoIndent(", ")
}
repeat(expression.valueArgumentsCount) { i -> p.printWithNoIndent("(")
expression.getValueArgument(i)?.let {
// TODO introduce a flag to print receiver this way?
//
// expression.extensionReceiver?.let {
// p.printWithNoIndent("\$receiver = ")
// it.acceptVoid(this)
// if (expression.valueArgumentsCount > 0) p.printWithNoIndent(", ")
// }
repeat(valueArgumentsCount) { i ->
getValueArgument(i)?.let {
if (i > 0) p.printWithNoIndent(", ") if (i > 0) p.printWithNoIndent(", ")
// TODO flag to print param name
p.printWithNoIndent(declaration.valueParameters[i].name.asString() + " = ") p.printWithNoIndent(declaration.valueParameters[i].name.asString() + " = ")
it.acceptVoid(this) it.acceptVoid(this@KotlinLikeDumper)
} }
} }
p.printWithNoIndent(")") p.printWithNoIndent(")")
} }
override fun visitConstructorCall(expression: IrConstructorCall) {
// TODO
p.printWithNoIndent("TODO(\"IrConstructorCall\")")
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
// TODO // TODO
p.printWithNoIndent("TODO(\"IrDelegatingConstructorCall\")") p.printWithNoIndent("TODO(\"IrDelegatingConstructorCall\")")
@@ -939,6 +988,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
override fun visitVararg(expression: IrVararg) { override fun visitVararg(expression: IrVararg) {
// TODO ???
p.printWithNoIndent("[") p.printWithNoIndent("[")
expression.elements.forEachIndexed { i, e -> expression.elements.forEachIndexed { i, e ->
if (i > 0) p.printWithNoIndent(", ") if (i > 0) p.printWithNoIndent(", ")