[IR] Add body printing strategy to Kotlin-like dumper
This commit is contained in:
committed by
Space Team
parent
ca8af7786e
commit
89ff7bd0db
@@ -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
@@ -1,5 +1,6 @@
|
||||
interface IFooBar {
|
||||
abstract fun foo()
|
||||
|
||||
abstract fun bar()
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
interface IFooBar {
|
||||
abstract fun foo()
|
||||
|
||||
abstract fun bar()
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Vendored
+1
@@ -14,6 +14,7 @@ interface IFoo {
|
||||
|
||||
@Ann
|
||||
abstract fun testFun()
|
||||
|
||||
@Ann
|
||||
abstract val String.testExtVal: String
|
||||
abstract get
|
||||
|
||||
+1
@@ -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
|
||||
|
||||
|
||||
+1
@@ -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
@@ -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>)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user