[IR] KotlinLikeDumper.kt: cleanup

This commit is contained in:
Zalim Bashorov
2020-11-13 18:22:22 +03:00
committed by teamcityserver
parent 5b0efe2b64
commit 92dda5cd92
@@ -16,28 +16,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
// TODO look at
// IrSourcePrinter.kt -- androidx-master-dev/frameworks/support/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/IrSourcePrinter.kt
// DumpIrTree.kt -- compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt
// RenderIrElement.kt --
/* TODO
* origin : class, function, property, ...
* don't print any members in interfaces? // or just print something like /* Any members */
* @<init>(...) Function2<AStringUnit> // (...) -> ...
* IrEnumEntryImpl
* replace `if (cond) p.printWithNoIndent(something)` with `p(cond, something)`
* use FQNs?
* don't print coercion to Unit on top level? blocks?
* name & ordinal in enums
* special render for accessors?
* FlexibleNullability
* ExtensionFunctionType
* don't crash on unbound symbols
* unique ids for symbols, or SignatureID?
* "normalize" names for tmps?
*/
fun IrElement.dumpKotlinLike(options: KotlinLikeDumpOptions = KotlinLikeDumpOptions()): String { fun IrElement.dumpKotlinLike(options: KotlinLikeDumpOptions = KotlinLikeDumpOptions()): String {
val sb = StringBuilder() val sb = StringBuilder()
accept(KotlinLikeDumper(Printer(sb, 1, " "), options), null) accept(KotlinLikeDumper(Printer(sb, 1, " "), options), null)
@@ -49,14 +27,14 @@ class KotlinLikeDumpOptions(
val printFileName: Boolean = true, val printFileName: Boolean = true,
val printFilePath: Boolean = true, val printFilePath: Boolean = true,
val useNamedArguments: Boolean = false, val useNamedArguments: Boolean = false,
val labelStrategy: LabelPrintingStrategy = LabelPrintingStrategy.NEVER, val labelPrintingStrategy: LabelPrintingStrategy = LabelPrintingStrategy.NEVER,
val printFakeOverridesStrategy: FakeOverridesStrategy = FakeOverridesStrategy.ALL, val printFakeOverridesStrategy: FakeOverridesStrategy = FakeOverridesStrategy.ALL,
/* /*
visibility? TODO add more options:
modality always print visibility?
special names?
print fake overrides
omit local visibility? omit local visibility?
always print modality
print special names as is, and other strategies?
print body for default accessors print body for default accessors
print get/set for default accessors print get/set for default accessors
print type of expressions print type of expressions
@@ -77,11 +55,33 @@ enum class FakeOverridesStrategy {
NONE NONE
} }
/* TODO:
* don't crash on unbound symbols
* origin : class, function, property, ...
* option?
* don't print members of kotlin.Any in interfaces? // or just print something like /* Any members */
* option?
* use lambda syntax for FunctionN, including extension lambdas (@ExtensionFunctionType)
* option?
* use FQNs?
* option?
* don't print coercion to Unit on top level? and inside blocks?
* option?
* special render for call site of accessors?
* option?
* FlexibleNullability is it about `T!`?
* option?
* unique ids for symbols, or SignatureID?
* option?
* "normalize" names for tmps? ^^ Could unique ids help?
* wrap/escape invalid identifiers with "`", like "$$delegate"
*/
private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOptions) : IrElementVisitor<Unit, IrDeclaration?> { private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOptions) : IrElementVisitor<Unit, IrDeclaration?> {
override fun visitElement(element: IrElement, data: IrDeclaration?) { override fun visitElement(element: IrElement, data: IrDeclaration?) {
val e = "/* ERROR: unsupported element type: " + element.javaClass.simpleName + " */" val e = "/* ERROR: unsupported element type: " + element.javaClass.simpleName + " */"
if (element is IrExpression) { if (element is IrExpression) {
// TODO message? // TODO move text to the message?
// TODO better process expressions and statements // TODO better process expressions and statements
p.printlnWithNoIndent("error(\"\") $e") p.printlnWithNoIndent("error(\"\") $e")
} else { } else {
@@ -123,9 +123,8 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
override fun visitClass(declaration: IrClass, data: IrDeclaration?) { override fun visitClass(declaration: IrClass, data: IrDeclaration?) {
// TODO omit super class for enums, annotations? // TODO omit super class for enums, annotations?
// TODO omit Companion name for companion objects? // TODO omit Companion name for companion objects?
// TODO thisReceiver // TODO do we need to print info about `thisReceiver`?
// TODO primary constructor? // TODO special support for objects?
// TODO special support for objects
declaration.printlnAnnotations() declaration.printlnAnnotations()
p.printIndent() p.printIndent()
@@ -158,16 +157,10 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
declaration.printTypeParametersWithNoIndent() declaration.printTypeParametersWithNoIndent()
if (declaration.superTypes.isNotEmpty()) { if (declaration.superTypes.isNotEmpty()) {
var first = true for ((i, type) in declaration.superTypes.withIndex()) {
for (type in declaration.superTypes) {
if (type.isAny()) continue if (type.isAny()) continue
if (!first) { p.printWithNoIndent(if (i > 0) ", " else " : ")
p.printWithNoIndent(", ")
} else {
p.printWithNoIndent(" : ")
first = false
}
type.printTypeWithNoIndent() type.printTypeWithNoIndent()
} }
@@ -239,7 +232,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
p(modality, defaultModality) { name.toLowerCase() } p(modality, defaultModality) { name.toLowerCase() }
p(isExternal, "external") p(isExternal, "external")
p(isFakeOverride, "fake") // TODO p(isFakeOverride, "fake")
p(isOverride, "override") p(isOverride, "override")
p(isLateinit, "lateinit") p(isLateinit, "lateinit")
p(isTailrec, "tailrec") p(isTailrec, "tailrec")
@@ -284,16 +277,10 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
if (typeParameters.isEmpty()) return if (typeParameters.isEmpty()) return
p.printWithNoIndent("<") p.printWithNoIndent("<")
var first = true typeParameters.forEachIndexed { i, typeParam ->
// TODO no commas in some types p(i > 0, ",")
typeParameters.forEach {
if (!first) {
p.printWithNoIndent(", ")
} else {
first = false
}
it.printATypeParameterWithNoIndent() typeParam.printATypeParameterWithNoIndent()
} }
p.printWithNoIndent(">") p.printWithNoIndent(">")
p.printWithNoIndent(postfix) p.printWithNoIndent(postfix)
@@ -301,7 +288,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
private fun IrTypeParameter.printATypeParameterWithNoIndent() { private fun IrTypeParameter.printATypeParameterWithNoIndent() {
variance.printVarianceWithNoIndent() variance.printVarianceWithNoIndent()
if (isReified) p.printWithNoIndent("reified ") p(isReified, "reified")
printAnnotationsWithNoIndent() printAnnotationsWithNoIndent()
@@ -355,7 +342,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
private fun IrTypeParameter.printWhereClauseTypesWithNoIndent(first: Boolean): Boolean { private fun IrTypeParameter.printWhereClauseTypesWithNoIndent(first: Boolean): Boolean {
var myFirst = first var myFirst = first
superTypes.forEachIndexed { i, superType -> superTypes.forEach { type ->
if (!myFirst) { if (!myFirst) {
p.printWithNoIndent(", ") p.printWithNoIndent(", ")
} else { } else {
@@ -364,14 +351,14 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
p.printWithNoIndent(name.asString()) p.printWithNoIndent(name.asString())
p.printWithNoIndent(" : ") p.printWithNoIndent(" : ")
superType.printTypeWithNoIndent() type.printTypeWithNoIndent()
} }
return myFirst return myFirst
} }
private fun IrType.printTypeWithNoIndent() { private fun IrType.printTypeWithNoIndent() {
// TODO don't print `Any?` upper bound? // TODO don't print `Any?` as upper bound?
printAnnotationsWithNoIndent() printAnnotationsWithNoIndent()
when (this) { when (this) {
is IrSimpleType -> { is IrSimpleType -> {
@@ -381,20 +368,15 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
if (arguments.isNotEmpty()) { if (arguments.isNotEmpty()) {
p.printWithNoIndent("<") p.printWithNoIndent("<")
var first = true arguments.forEachIndexed { i, typeArg ->
arguments.forEach { p(i > 0, ",")
if (!first) {
p.printWithNoIndent(", ")
} else {
first = false
}
when (it) { when (typeArg) {
is IrStarProjection -> is IrStarProjection ->
p.printWithNoIndent("*") p.printWithNoIndent("*")
is IrTypeProjection -> { is IrTypeProjection -> {
it.variance.printVarianceWithNoIndent() typeArg.variance.printVarianceWithNoIndent()
it.type.printTypeWithNoIndent() typeArg.type.printTypeWithNoIndent()
} }
} }
} }
@@ -421,7 +403,6 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
p.printWithNoIndent("typealias ") p.printWithNoIndent("typealias ")
p.printWithNoIndent(declaration.name.asString()) p.printWithNoIndent(declaration.name.asString())
// TODO IrDump doesn't have typeparameters
declaration.printTypeParametersWithNoIndent() declaration.printTypeParametersWithNoIndent()
p.printWithNoIndent(" = ") p.printWithNoIndent(" = ")
declaration.expandedType.printTypeWithNoIndent() declaration.expandedType.printTypeWithNoIndent()
@@ -449,11 +430,11 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer, data: IrDeclaration?) { override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer, data: IrDeclaration?) {
// Looks like IrAnonymousInitializer has annotations accidentally. No tests. // TODO no tests, looks like IrAnonymousInitializer has annotations accidentally.
declaration.printlnAnnotations() declaration.printlnAnnotations()
p.printIndent() p.printIndent()
// TODO looks like there are no irText tests for isStatic flag // TODO no tests, looks like there are no irText tests for isStatic flag
p(declaration.isStatic, commentBlockH("static")) p(declaration.isStatic, commentBlockH("static"))
p.printWithNoIndent("init ") p.printWithNoIndent("init ")
declaration.body.accept(this, declaration) declaration.body.accept(this, declaration)
@@ -472,7 +453,6 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
override fun visitConstructor(declaration: IrConstructor, data: IrDeclaration?) { override fun visitConstructor(declaration: IrConstructor, data: IrDeclaration?) {
// TODO primary!!!
// TODO name? // TODO name?
// TODO is it worth to merge code for IrConstructor and IrSimpleFunction? // TODO is it worth to merge code for IrConstructor and IrSimpleFunction?
// TODO dispatchReceiverParameter -- outer `this` for inner classes // TODO dispatchReceiverParameter -- outer `this` for inner classes
@@ -542,7 +522,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
isExpect, isExpect,
modality, modality,
isExternal, isExternal,
isOverride = overriddenSymbols.isNotEmpty(), // TODO override isOverride = overriddenSymbols.isNotEmpty(),
isFakeOverride, isFakeOverride,
isLateinit = INAPPLICABLE, isLateinit = INAPPLICABLE,
isTailrec, isTailrec,
@@ -593,15 +573,10 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
private fun IrFunction.printValueParametersWithNoIndent() { private fun IrFunction.printValueParametersWithNoIndent() {
p.printWithNoIndent("(") p.printWithNoIndent("(")
var first = true valueParameters.forEachIndexed { i, param ->
valueParameters.forEach { p(i > 0, ",")
if (!first) {
p.printWithNoIndent(", ")
} else {
first = false
}
it.printAValueParameterWithNoIndent(this) param.printAValueParameterWithNoIndent(this)
} }
p.printWithNoIndent(")") p.printWithNoIndent(")")
} }
@@ -647,7 +622,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
p.printIndent() p.printIndent()
// TODO better rendering for modifiers on property and accessors // TODO better rendering for modifiers on property and accessors
// modifiers that could be different between accessors and property have a comment // modifiers that could be different between accessors and property have a comment
declaration.run { declaration.run {
printModifiersWithNoIndent( printModifiersWithNoIndent(
// accessors by default have same visibility, but the can define own value // accessors by default have same visibility, but the can define own value
@@ -675,7 +650,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
) )
} }
// TODO don't print borrowed flags and assert that they are same with setter(???) or don't borrow? // TODO don't print borrowed flags and assert that they are same with a setter or don't borrow?
// TODO we can omit type for set parameter // TODO we can omit type for set parameter
p(declaration.isConst, "const") p(declaration.isConst, "const")
@@ -877,7 +852,6 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
override fun visitConstructorCall(expression: IrConstructorCall, data: IrDeclaration?) { override fun visitConstructorCall(expression: IrConstructorCall, data: IrDeclaration?) {
// TODO could constructors have receiver?
val clazz = expression.symbol.owner.parentAsClass val clazz = expression.symbol.owner.parentAsClass
expression.printMemberAccessExpressionWithNoIndent( expression.printMemberAccessExpressionWithNoIndent(
clazz.name.asString(), clazz.name.asString(),
@@ -917,9 +891,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
if (superQualifierSymbol == null) it.accept(this@KotlinLikeDumper, data) if (superQualifierSymbol == null) it.accept(this@KotlinLikeDumper, data)
// else assert dispatchReceiver === this // else assert dispatchReceiver === this
} }
if (twoReceivers) { p(twoReceivers, ",")
p.printWithNoIndent(", ")
}
extensionReceiver?.accept(this@KotlinLikeDumper, data) extensionReceiver?.accept(this@KotlinLikeDumper, data)
if (twoReceivers) { if (twoReceivers) {
p.printWithNoIndent(")") p.printWithNoIndent(")")
@@ -948,9 +920,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
if (typeArgumentsCount > 0) { if (typeArgumentsCount > 0) {
p.printWithNoIndent("<") p.printWithNoIndent("<")
repeat(typeArgumentsCount) { repeat(typeArgumentsCount) {
if (it > 0) { p(it > 0, ",")
p.printWithNoIndent(", ")
}
// TODO flag to print type param name? // TODO flag to print type param name?
getTypeArgument(it)!!.printTypeWithNoIndent() getTypeArgument(it)!!.printTypeWithNoIndent()
} }
@@ -970,7 +940,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
repeat(valueArgumentsCount) { i -> repeat(valueArgumentsCount) { i ->
// TODO should we print something for omitted arguments (== null)? // TODO should we print something for omitted arguments (== null)?
getValueArgument(i)?.let { getValueArgument(i)?.let {
if (i > 0) p.printWithNoIndent(", ") p(i > 0, ",")
// TODO flag to print param name // TODO flag to print param name
p.printWithNoIndent(valueParameters[i].name.asString() + " = ") p.printWithNoIndent(valueParameters[i].name.asString() + " = ")
it.accept(this@KotlinLikeDumper, data) it.accept(this@KotlinLikeDumper, data)
@@ -1097,6 +1067,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
override fun visitReturn(expression: IrReturn, data: IrDeclaration?) { override fun visitReturn(expression: IrReturn, data: IrDeclaration?) {
// TODO label // TODO label
// TODO optionally don't print Unit when return type of returnTargetSymbol is Unit
p.printWithNoIndent("return ") p.printWithNoIndent("return ")
expression.value.accept(this, data) expression.value.accept(this, data)
} }
@@ -1107,12 +1078,10 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
override fun visitStringConcatenation(expression: IrStringConcatenation, data: IrDeclaration?) { override fun visitStringConcatenation(expression: IrStringConcatenation, data: IrDeclaration?) {
// TODO escape? see IrTextTestCaseGenerated.Expressions#testStringTemplates // TODO escape char symbols, use triple quotes when possible, see IrTextTestCaseGenerated.Expressions#testStringTemplates
// TODO optionally each argument at a separate line, another option add a wrapping // TODO optionally each argument at a separate line, another option add a wrapping
expression.arguments.forEachIndexed { i, e -> expression.arguments.forEachIndexed { i, e ->
if (i > 0) { p(i > 0, " +")
p.printWithNoIndent(" + ")
}
e.accept(this, data) e.accept(this, data)
} }
} }
@@ -1137,11 +1106,11 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
} }
override fun visitVararg(expression: IrVararg, data: IrDeclaration?) { override fun visitVararg(expression: IrVararg, data: IrDeclaration?) {
// TODO ??? // TODO better rendering?
// TODO varargElementType // TODO varargElementType
p.printWithNoIndent("[") p.printWithNoIndent("[")
expression.elements.forEachIndexed { i, e -> expression.elements.forEachIndexed { i, e ->
if (i > 0) p.printWithNoIndent(", ") p(i > 0, ",")
e.accept(this, data) e.accept(this, data)
} }
p.printWithNoIndent("]") p.printWithNoIndent("]")
@@ -1341,7 +1310,7 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
expression.receiver.accept(this, data) expression.receiver.accept(this, data)
p.printWithNoIndent(s.first) p.printWithNoIndent(s.first)
expression.arguments.forEachIndexed { i, e -> expression.arguments.forEachIndexed { i, e ->
if (i > 0) p.printWithNoIndent(", ") p(i > 0, ",")
e.accept(this, data) e.accept(this, data)
} }
p.printWithNoIndent(s.second) p.printWithNoIndent(s.second)