[IR] Add body printing strategy to Kotlin-like dumper

This commit is contained in:
Sergej Jaskiewicz
2023-05-01 18:55:42 +02:00
committed by Space Team
parent ca8af7786e
commit 89ff7bd0db
36 changed files with 165 additions and 39 deletions
@@ -64,6 +64,7 @@ class KotlinLikeDumpOptions(
// TODO support
val labelPrintingStrategy: LabelPrintingStrategy = LabelPrintingStrategy.NEVER,
val printFakeOverridesStrategy: FakeOverridesStrategy = FakeOverridesStrategy.ALL,
val bodyPrintingStrategy: BodyPrintingStrategy = BodyPrintingStrategy.PRINT_BODIES,
val printElseAsTrue: Boolean = false,
/*
TODO add more options:
@@ -91,6 +92,12 @@ enum class FakeOverridesStrategy {
NONE
}
enum class BodyPrintingStrategy {
NO_BODIES,
PRINT_ONLY_LOCAL_CLASSES_AND_FUNCTIONS,
PRINT_BODIES,
}
// TODO_ conventions:
// TODO support -- for unsupported nodes
// TODO no test -- for the cases with no test(s)
@@ -118,29 +125,33 @@ enum class FakeOverridesStrategy {
*/
private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOptions) : IrElementVisitor<Unit, IrDeclaration?> {
private val IrSymbol.safeName get() = if (!isBound) {
"/* ERROR: unbound symbol $signature */"
} else {
(owner as? IrDeclarationWithName)?.name?.toString() ?: "/* ERROR: unnamed symbol $signature */"
}
private val IrSymbol.safeName
get() = if (!isBound) {
"/* ERROR: unbound symbol $signature */"
} else {
(owner as? IrDeclarationWithName)?.name?.toString() ?: "/* ERROR: unnamed symbol $signature */"
}
private val IrFunctionSymbol.safeValueParameters get() = if (!isBound) {
emptyList()
} else {
owner.valueParameters
}
private val IrFunctionSymbol.safeValueParameters
get() = if (!isBound) {
emptyList()
} else {
owner.valueParameters
}
private val IrSymbol.safeParentClassName get() = if (!isBound) {
"/* ERROR: unbound symbol $signature */"
} else {
(owner as? IrDeclaration)?.parentClassOrNull?.name?.toString() ?: "/* ERROR: unexpected parent for $safeName */"
}
private val IrSymbol.safeParentClassName
get() = if (!isBound) {
"/* ERROR: unbound symbol $signature */"
} else {
(owner as? IrDeclaration)?.parentClassOrNull?.name?.toString() ?: "/* ERROR: unexpected parent for $safeName */"
}
private val IrSymbol.safeParentClassOrNull get() = if (!isBound) {
null
} else {
(owner as? IrDeclaration)?.parentClassOrNull
}
private val IrSymbol.safeParentClassOrNull
get() = if (!isBound) {
null
} else {
(owner as? IrDeclaration)?.parentClassOrNull
}
fun printElement(element: IrElement) {
@@ -510,8 +521,10 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
p.printIndent()
p.printWithNoIndent(declaration.name)
declaration.initializerExpression?.let {
// it's not valid kotlin
p.printWithNoIndent(" = ")
if (options.bodyPrintingStrategy == BodyPrintingStrategy.PRINT_BODIES) {
// it's not valid kotlin
p.printWithNoIndent(" = ")
}
it.accept(this, declaration)
}
p.println()
@@ -528,7 +541,10 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
// TODO no tests, looks like there are no irText tests for isStatic flag
p(declaration.isStatic, customModifier("static"))
p.printWithNoIndent("init ")
p.printWithNoIndent("init")
if (options.bodyPrintingStrategy == BodyPrintingStrategy.PRINT_BODIES) {
p.printWithNoIndent(" ")
}
declaration.body.accept(this, declaration)
p.printlnWithNoIndent()
@@ -582,9 +598,15 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
declaration.printTypeParametersWithNoIndent()
declaration.printValueParametersWithNoIndent()
declaration.printWhereClauseIfNeededWithNoIndent()
p.printWithNoIndent(" ")
p(declaration.isPrimary, customModifier("primary"))
declaration.body?.accept(this, declaration)
if (declaration.isPrimary) {
p.printWithNoIndent(" ", customModifier("primary"))
}
declaration.body?.let {
if (options.bodyPrintingStrategy == BodyPrintingStrategy.PRINT_BODIES) {
p.printWithNoIndent(" ")
}
it.accept(this, declaration)
}
p.printlnWithNoIndent()
}
@@ -654,10 +676,15 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
printWhereClauseIfNeededWithNoIndent()
body?.let {
p.printWithNoIndent(" ")
if (options.bodyPrintingStrategy == BodyPrintingStrategy.PRINT_BODIES) {
p.printWithNoIndent(" ")
}
it.accept(this@KotlinLikeDumper, null)
}
} else {
}
if (!printSignatureAndBody || body == null || options.bodyPrintingStrategy != BodyPrintingStrategy.PRINT_BODIES) {
p.printlnWithNoIndent()
}
}
@@ -696,7 +723,9 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
// TODO print it.type too for varargs?
defaultValue?.let { v ->
p.printWithNoIndent(" = ")
if (options.bodyPrintingStrategy == BodyPrintingStrategy.PRINT_BODIES) {
p.printWithNoIndent(" = ")
}
v.accept(this@KotlinLikeDumper, data)
}
}
@@ -781,7 +810,9 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
* provideDelegate
*/
p(declaration.isDelegated, " " + commentBlock("by"))
if (declaration.isDelegated) {
p.printWithNoIndent(" ", commentBlock("by"))
}
p.printlnWithNoIndent()
p.pushIndent()
@@ -789,9 +820,18 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
// TODO share code with visitField?
// it's not valid kotlin
declaration.backingField?.initializer?.let {
p.print("field = ")
if (options.bodyPrintingStrategy != BodyPrintingStrategy.NO_BODIES) {
// If the strategy is PRINT_ONLY_LOCAL_CLASSES_AND_FUNCTIONS, the local declarations in the backing field initializer
// will be printed under 'field'.
p.print("field")
}
if (options.bodyPrintingStrategy == BodyPrintingStrategy.PRINT_BODIES) {
p.printWithNoIndent(" = ")
}
it.accept(this, declaration)
p.printlnWithNoIndent()
if (options.bodyPrintingStrategy != BodyPrintingStrategy.NO_BODIES) {
p.printlnWithNoIndent()
}
}
// TODO generate better name for set parameter `<set-?>`?
@@ -851,7 +891,9 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
declaration.type.printTypeWithNoIndent()
declaration.initializer?.let {
p.printWithNoIndent(" = ")
if (options.bodyPrintingStrategy == BodyPrintingStrategy.PRINT_BODIES) {
p.printWithNoIndent(" = ")
}
it.accept(this, declaration)
}
@@ -902,14 +944,49 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
type.printTypeWithNoIndent()
}
private fun <Body : IrBody> printBody(body: Body, data: IrDeclaration?, actuallyPrint: () -> Unit) {
when (options.bodyPrintingStrategy) {
BodyPrintingStrategy.NO_BODIES -> {}
BodyPrintingStrategy.PRINT_ONLY_LOCAL_CLASSES_AND_FUNCTIONS -> body.acceptChildren(
// Don't print bodies, but print local classes and functions declared in those bodies
object : IrElementVisitor<Unit, IrDeclaration?> {
override fun visitElement(element: IrElement, data: IrDeclaration?) {
element.acceptChildren(this, data)
}
override fun visitDeclaration(declaration: IrDeclarationBase, data: IrDeclaration?) {
p.println()
p.pushIndent()
declaration.accept(this@KotlinLikeDumper, data)
p.popIndent()
}
override fun visitVariable(declaration: IrVariable, data: IrDeclaration?) {
declaration.acceptChildren(this, data)
}
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty, data: IrDeclaration?) {
declaration.acceptChildren(this, data)
}
},
data
)
BodyPrintingStrategy.PRINT_BODIES -> actuallyPrint()
}
}
override fun visitExpressionBody(body: IrExpressionBody, data: IrDeclaration?) {
// TODO should we print something here?
body.expression.accept(this, data)
printBody(body, data) {
// TODO should we print something here?
body.expression.accept(this, data)
}
}
override fun visitBlockBody(body: IrBlockBody, data: IrDeclaration?) {
body.printStatementContainer("{", "}", data)
p.printlnWithNoIndent()
printBody(body, data) {
body.printStatementContainer("{", "}", data)
p.printlnWithNoIndent()
}
}
override fun visitComposite(expression: IrComposite, data: IrDeclaration?) {
@@ -950,8 +1027,10 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
}
override fun visitSyntheticBody(body: IrSyntheticBody, data: IrDeclaration?) {
// it's not valid kotlin
p.printlnWithNoIndent("/* Synthetic body for ${body.kind} */")
printBody(body, data) {
// it's not valid kotlin
p.printlnWithNoIndent("/* Synthetic body for ${body.kind} */")
}
}
override fun visitCall(expression: IrCall, data: IrDeclaration?) {
@@ -6,6 +6,7 @@ abstract class AbstractClass {
}
abstract fun abstractFun()
abstract val abstractVal: Int
abstract get
@@ -17,6 +18,7 @@ abstract class AbstractClass {
interface Interface {
abstract fun abstractFun()
abstract val abstractVal: Int
abstract get
@@ -62,6 +62,7 @@ class C {
interface NestedInterface {
abstract fun foo()
fun bar() {
return <this>.foo()
}
@@ -1,5 +1,6 @@
interface IBase<A : Any?> {
abstract fun <B : Any?> foo(a: A, b: B)
abstract val <C : Any?> C.id: Map<A, C>?
abstract get
@@ -1,5 +1,6 @@
interface IBase<A : Any?> {
abstract fun <B : Any?> foo(a: A, b: B)
abstract val <C : Any?> C.id: Map<A, C>?
abstract get
@@ -1,6 +1,8 @@
interface IBase {
abstract fun foo(x: Int, s: String)
abstract fun bar(): Int
abstract fun String.qux()
}
@@ -1,6 +1,8 @@
interface IBase {
abstract fun foo(x: Int, s: String)
abstract fun bar(): Int
abstract fun String.qux()
}
@@ -1,5 +1,6 @@
interface IFooBar {
abstract fun foo()
abstract fun bar()
}
@@ -1,5 +1,6 @@
interface IFooBar {
abstract fun foo()
abstract fun bar()
}
+2
View File
@@ -66,6 +66,7 @@ abstract enum class TestEnum3 : Enum<TestEnum3> {
}
abstract fun foo()
fun values(): Array<TestEnum3> /* Synthetic body for ENUM_VALUES */
fun valueOf(value: String): TestEnum3 /* Synthetic body for ENUM_VALUEOF */
@@ -122,6 +123,7 @@ abstract enum class TestEnum4 : Enum<TestEnum4> {
}
abstract fun foo()
fun values(): Array<TestEnum4> /* Synthetic body for ENUM_VALUES */
fun valueOf(value: String): TestEnum4 /* Synthetic body for ENUM_VALUEOF */
@@ -142,6 +142,7 @@ abstract enum class TestAbstractEnum1 : Enum<TestAbstractEnum1> {
}
abstract fun foo()
fun values(): Array<TestAbstractEnum1> /* Synthetic body for ENUM_VALUES */
fun valueOf(value: String): TestAbstractEnum1 /* Synthetic body for ENUM_VALUEOF */
@@ -96,6 +96,7 @@ abstract enum class Test2 : Enum<Test2> {
}
abstract fun foo()
fun values(): Array<Test2> /* Synthetic body for ENUM_VALUES */
fun valueOf(value: String): Test2 /* Synthetic body for ENUM_VALUEOF */
@@ -16,6 +16,7 @@ open class Base {
interface BaseI {
abstract fun foo()
abstract val bar: String
abstract get
@@ -14,6 +14,7 @@ interface IFoo {
@Ann
abstract fun testFun()
@Ann
abstract val String.testExtVal: String
abstract get
@@ -14,6 +14,7 @@ interface IFoo {
@Ann
abstract fun testFun()
@Ann
abstract val String.testExtVal: String
abstract get
@@ -7,6 +7,7 @@ fun outer() {
}
abstract fun afun()
abstract val aval: Int
abstract get
@@ -7,6 +7,7 @@ expect abstract class A {
expect open class B : A {
expect constructor(i: Int) /* primary */
expect override fun foo()
expect open fun bar(s: String)
}
@@ -1,5 +1,6 @@
interface IBase<T : Any?> {
abstract fun foo(x: Int)
abstract val bar: Int
abstract get
@@ -1,5 +1,6 @@
interface IBase<T : Any?> {
abstract fun foo(x: Int)
abstract val bar: Int
abstract get
@@ -1,5 +1,6 @@
interface IFoo {
abstract fun foo()
fun bar() {
<this>.foo()
}
@@ -1,5 +1,6 @@
interface Visitor {
abstract fun visit()
fun visitArray(): Visitor? {
return null
}
@@ -1,5 +1,6 @@
interface Visitor {
abstract fun visit()
fun visitArray(): Visitor? {
return null
}
@@ -9,7 +9,9 @@ sealed class ArrayMap<T : Any> : Iterable<T> {
abstract get
abstract operator fun set(index: Int, value: T)
abstract operator fun get(index: Int): T?
abstract fun copy(): ArrayMap<T>
}
@@ -9,7 +9,9 @@ sealed class ArrayMap<T : Any> : Iterable<T> {
abstract get
abstract operator fun set(index: Int, value: T)
abstract operator fun get(index: Int): T?
abstract fun copy(): ArrayMap<T>
}
@@ -4,7 +4,9 @@ interface IrType {
interface TypeRemapper {
abstract fun enterScope(irTypeParametersContainer: IrTypeParametersContainer)
abstract fun remapType(type: IrType): IrType
abstract fun leaveScope()
}
@@ -4,7 +4,9 @@ interface IrType {
interface TypeRemapper {
abstract fun enterScope(irTypeParametersContainer: IrTypeParametersContainer)
abstract fun remapType(type: IrType): IrType
abstract fun leaveScope()
}
@@ -13,6 +13,7 @@ abstract class Base<T : Any?> {
get
abstract fun <Y : Any?> foo(y: Y): T
abstract var bar: T
abstract get
abstract set
@@ -13,6 +13,7 @@ abstract class Base<T : Any?> {
get
abstract fun <Y : Any?> foo(y: Y): T
abstract var bar: T
abstract get
abstract set
@@ -1,5 +1,6 @@
interface B<T1 : Any?> : A<T1> {
abstract override fun foo(x: T1): T1
abstract override fun bar(x: (T1 & Any)): (T1 & Any)
}
@@ -1,5 +1,6 @@
interface B<T1 : Any?> : A<T1> {
abstract override fun foo(x: T1): T1
abstract override fun bar(x: (T1 & Any)): (T1 & Any)
}
@@ -1,5 +1,6 @@
interface I<T : Any?> {
abstract fun input(t: T)
abstract fun output(): T
}
@@ -1,5 +1,6 @@
interface I<T : Any?> {
abstract fun input(t: T)
abstract fun output(): T
}
@@ -22,6 +22,7 @@ abstract class Box<T> : IFoo, IBar where T : IFoo, T : IBar {
}
abstract fun <F> foo(tSerializer: I<F>): I<Box<F>> where F : IFoo, F : IBar
fun bar(vararg serializers: I<*>): I<*> {
return <this>.foo<IFoo>(tSerializer = serializers.get(index = 0))
}
@@ -22,6 +22,7 @@ abstract class Box<T> : IFoo, IBar where T : IFoo, T : IBar {
}
abstract fun <F> foo(tSerializer: I<F>): I<Box<F>> where F : IFoo, F : IBar
fun bar(vararg serializers: I<*>): I<*> {
return <this>.foo<IBase>(tSerializer = serializers.get(index = 0))
}
@@ -1,7 +1,10 @@
interface K {
abstract fun kf1(): Collection<out CharSequence>
abstract fun kf2(): Collection<CharSequence>
abstract fun kg1(c: Collection<out CharSequence>)
abstract fun kg2(c: Collection<CharSequence>)
}
@@ -1,7 +1,10 @@
interface K {
abstract fun kf1(): Collection<out CharSequence>
abstract fun kf2(): Collection<CharSequence>
abstract fun kg1(c: Collection<out CharSequence>)
abstract fun kg2(c: Collection<CharSequence>)
}