[IR] Introduce DumpIrTreeOptions for customizing IR dump
We plan to add more options => using a data class is better than multiple function parameters
This commit is contained in:
committed by
Space Team
parent
1a8d5056bf
commit
3deea96b53
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.util
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.IrFileEntry
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
|
||||||
|
@Deprecated(
|
||||||
|
"Use the overload with DumpIrTreeOptions instead.",
|
||||||
|
ReplaceWith(
|
||||||
|
"dump(DumpIrTreeOptions(normalizeNames = normalizeNames, stableOrder = stableOrder))",
|
||||||
|
"org.jetbrains.kotlin.ir.util.DumpIrTreeOptions",
|
||||||
|
),
|
||||||
|
DeprecationLevel.ERROR,
|
||||||
|
)
|
||||||
|
fun IrElement.dump(normalizeNames: Boolean = false, stableOrder: Boolean = false) =
|
||||||
|
dump(DumpIrTreeOptions(normalizeNames = normalizeNames, stableOrder = stableOrder))
|
||||||
|
|
||||||
|
@Deprecated(
|
||||||
|
"Use the overload with DumpIrTreeOptions instead.",
|
||||||
|
ReplaceWith(
|
||||||
|
"dumpTreesFromLineNumber(lineNumber, DumpIrTreeOptions(normalizeNames = normalizeNames))",
|
||||||
|
"org.jetbrains.kotlin.ir.util.DumpIrTreeOptions",
|
||||||
|
),
|
||||||
|
DeprecationLevel.ERROR,
|
||||||
|
)
|
||||||
|
fun IrFile.dumpTreesFromLineNumber(lineNumber: Int, normalizeNames: Boolean = false) =
|
||||||
|
dumpTreesFromLineNumber(lineNumber, DumpIrTreeOptions(normalizeNames = normalizeNames))
|
||||||
|
|
||||||
|
@Deprecated(
|
||||||
|
"Use the overload with DumpIrTreeOptions instead.",
|
||||||
|
ReplaceWith(
|
||||||
|
"DumpTreeFromSourceLineVisitor(fileEntry, lineNumber, out, DumpIrTreeOptions(normalizeNames = normalizeNames))",
|
||||||
|
"org.jetbrains.kotlin.ir.util.DumpIrTreeOptions",
|
||||||
|
),
|
||||||
|
DeprecationLevel.ERROR,
|
||||||
|
)
|
||||||
|
fun DumpTreeFromSourceLineVisitor(fileEntry: IrFileEntry, lineNumber: Int, out: Appendable, normalizeNames: Boolean = false) =
|
||||||
|
DumpTreeFromSourceLineVisitor(fileEntry, lineNumber, out, DumpIrTreeOptions(normalizeNames = normalizeNames))
|
||||||
|
|
||||||
|
@Deprecated(
|
||||||
|
"Use the overload with DumpIrTreeOptions instead.",
|
||||||
|
ReplaceWith(
|
||||||
|
"DumpIrTreeVisitor(out, DumpIrTreeOptions(normalizeNames = normalizeNames, stableOrder = stableOrder))",
|
||||||
|
"org.jetbrains.kotlin.ir.util.DumpIrTreeOptions",
|
||||||
|
),
|
||||||
|
DeprecationLevel.ERROR,
|
||||||
|
)
|
||||||
|
fun DumpIrTreeVisitor(out: Appendable, normalizeNames: Boolean = false, stableOrder: Boolean = false) =
|
||||||
|
DumpIrTreeVisitor(out, DumpIrTreeOptions(normalizeNames = normalizeNames, stableOrder = stableOrder))
|
||||||
|
|
||||||
|
@Deprecated(
|
||||||
|
"Use the overload with DumpIrTreeOptions instead.",
|
||||||
|
ReplaceWith(
|
||||||
|
"RenderIrElementVisitor(DumpIrTreeOptions(normalizeNames = normalizeNames, stableOrder = !verboseErrorTypes))",
|
||||||
|
"org.jetbrains.kotlin.ir.util.DumpIrTreeOptions",
|
||||||
|
),
|
||||||
|
DeprecationLevel.ERROR,
|
||||||
|
)
|
||||||
|
fun RenderIrElementVisitor(normalizeNames: Boolean = false, verboseErrorTypes: Boolean = true) =
|
||||||
|
RenderIrElementVisitor(DumpIrTreeOptions(normalizeNames = normalizeNames, verboseErrorTypes = verboseErrorTypes))
|
||||||
@@ -21,28 +21,40 @@ import org.jetbrains.kotlin.ir.IrFileEntry
|
|||||||
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.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
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
|
||||||
import org.jetbrains.kotlin.utils.Printer
|
import org.jetbrains.kotlin.utils.Printer
|
||||||
|
|
||||||
fun IrElement.dump(normalizeNames: Boolean = false, stableOrder: Boolean = false): String =
|
fun IrElement.dump(options: DumpIrTreeOptions = DumpIrTreeOptions()): String =
|
||||||
try {
|
try {
|
||||||
StringBuilder().also { sb ->
|
StringBuilder().also { sb ->
|
||||||
accept(DumpIrTreeVisitor(sb, normalizeNames, stableOrder), "")
|
accept(DumpIrTreeVisitor(sb, options), "")
|
||||||
}.toString()
|
}.toString()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
"(Full dump is not available: ${e.message})\n" + render()
|
"(Full dump is not available: ${e.message})\n" + render(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrFile.dumpTreesFromLineNumber(lineNumber: Int, normalizeNames: Boolean = false): String {
|
fun IrFile.dumpTreesFromLineNumber(lineNumber: Int, options: DumpIrTreeOptions = DumpIrTreeOptions()): String {
|
||||||
if (shouldSkipDump()) return ""
|
if (shouldSkipDump()) return ""
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
accept(DumpTreeFromSourceLineVisitor(fileEntry, lineNumber, sb, normalizeNames), null)
|
accept(DumpTreeFromSourceLineVisitor(fileEntry, lineNumber, sb, options), null)
|
||||||
return sb.toString()
|
return sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property normalizeNames Rename temporary local variables using a stable naming scheme
|
||||||
|
* @property stableOrder Print declarations in a sorted order
|
||||||
|
* @property verboseErrorTypes Whether to dump the value of [IrErrorType.kotlinType] for [IrErrorType] nodes
|
||||||
|
*/
|
||||||
|
data class DumpIrTreeOptions(
|
||||||
|
val normalizeNames: Boolean = false,
|
||||||
|
val stableOrder: Boolean = false,
|
||||||
|
val verboseErrorTypes: Boolean = true,
|
||||||
|
)
|
||||||
|
|
||||||
private fun IrFile.shouldSkipDump(): Boolean {
|
private fun IrFile.shouldSkipDump(): Boolean {
|
||||||
val entry = fileEntry as? NaiveSourceBasedFileEntryImpl ?: return false
|
val entry = fileEntry as? NaiveSourceBasedFileEntryImpl ?: return false
|
||||||
return entry.lineStartOffsetsAreEmpty
|
return entry.lineStartOffsetsAreEmpty
|
||||||
@@ -81,15 +93,14 @@ internal fun List<IrDeclaration>.stableOrdered(): List<IrDeclaration> {
|
|||||||
|
|
||||||
class DumpIrTreeVisitor(
|
class DumpIrTreeVisitor(
|
||||||
out: Appendable,
|
out: Appendable,
|
||||||
normalizeNames: Boolean = false,
|
private val options: DumpIrTreeOptions = DumpIrTreeOptions(),
|
||||||
private val stableOrder: Boolean = false
|
|
||||||
) : IrElementVisitor<Unit, String> {
|
) : IrElementVisitor<Unit, String> {
|
||||||
|
|
||||||
private val printer = Printer(out, " ")
|
private val printer = Printer(out, " ")
|
||||||
private val elementRenderer = RenderIrElementVisitor(normalizeNames, !stableOrder)
|
private val elementRenderer = RenderIrElementVisitor(options)
|
||||||
private fun IrType.render() = elementRenderer.renderType(this)
|
private fun IrType.render() = elementRenderer.renderType(this)
|
||||||
|
|
||||||
private fun List<IrDeclaration>.ordered(): List<IrDeclaration> = if (stableOrder) stableOrdered() else this
|
private fun List<IrDeclaration>.ordered(): List<IrDeclaration> = if (options.stableOrder) stableOrdered() else this
|
||||||
|
|
||||||
override fun visitElement(element: IrElement, data: String) {
|
override fun visitElement(element: IrElement, data: String) {
|
||||||
element.dumpLabeledElementWith(data) {
|
element.dumpLabeledElementWith(data) {
|
||||||
@@ -434,9 +445,9 @@ class DumpTreeFromSourceLineVisitor(
|
|||||||
val fileEntry: IrFileEntry,
|
val fileEntry: IrFileEntry,
|
||||||
private val lineNumber: Int,
|
private val lineNumber: Int,
|
||||||
out: Appendable,
|
out: Appendable,
|
||||||
normalizeNames: Boolean = false
|
options: DumpIrTreeOptions,
|
||||||
) : IrElementVisitorVoid {
|
) : IrElementVisitorVoid {
|
||||||
private val dumper = DumpIrTreeVisitor(out, normalizeNames)
|
private val dumper = DumpIrTreeVisitor(out, options)
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
if (fileEntry.getLineNumber(element.startOffset) == lineNumber) {
|
if (fileEntry.getLineNumber(element.startOffset) == lineNumber) {
|
||||||
|
|||||||
@@ -23,33 +23,33 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
|||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
|
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
|
||||||
|
|
||||||
fun IrElement.render() =
|
fun IrElement.render(options: DumpIrTreeOptions = DumpIrTreeOptions()) =
|
||||||
accept(RenderIrElementVisitor(), null)
|
accept(RenderIrElementVisitor(options), null)
|
||||||
|
|
||||||
class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verboseErrorTypes: Boolean = true) :
|
class RenderIrElementVisitor(private val options: DumpIrTreeOptions = DumpIrTreeOptions()) :
|
||||||
IrElementVisitor<String, Nothing?> {
|
IrElementVisitor<String, Nothing?> {
|
||||||
|
|
||||||
private val variableNameData = VariableNameData(normalizeNames)
|
private val variableNameData = VariableNameData(options.normalizeNames)
|
||||||
|
|
||||||
fun renderType(type: IrType) = type.renderTypeWithRenderer(this@RenderIrElementVisitor, verboseErrorTypes)
|
fun renderType(type: IrType) = type.renderTypeWithRenderer(this@RenderIrElementVisitor, options)
|
||||||
|
|
||||||
fun renderSymbolReference(symbol: IrSymbol) = symbol.renderReference()
|
fun renderSymbolReference(symbol: IrSymbol) = symbol.renderReference()
|
||||||
|
|
||||||
fun renderAsAnnotation(irAnnotation: IrConstructorCall): String =
|
fun renderAsAnnotation(irAnnotation: IrConstructorCall): String =
|
||||||
StringBuilder().also { it.renderAsAnnotation(irAnnotation, this, verboseErrorTypes) }.toString()
|
StringBuilder().also { it.renderAsAnnotation(irAnnotation, this, options) }.toString()
|
||||||
|
|
||||||
private fun IrType.render(): String =
|
private fun IrType.render(): String =
|
||||||
this.renderTypeWithRenderer(this@RenderIrElementVisitor, verboseErrorTypes)
|
this.renderTypeWithRenderer(this@RenderIrElementVisitor, options)
|
||||||
|
|
||||||
private fun IrSymbol.renderReference() =
|
private fun IrSymbol.renderReference() =
|
||||||
if (isBound)
|
if (isBound)
|
||||||
owner.accept(BoundSymbolReferenceRenderer(variableNameData, verboseErrorTypes), null)
|
owner.accept(BoundSymbolReferenceRenderer(variableNameData, options), null)
|
||||||
else
|
else
|
||||||
"UNBOUND ${javaClass.simpleName}"
|
"UNBOUND ${javaClass.simpleName}"
|
||||||
|
|
||||||
private class BoundSymbolReferenceRenderer(
|
private class BoundSymbolReferenceRenderer(
|
||||||
private val variableNameData: VariableNameData,
|
private val variableNameData: VariableNameData,
|
||||||
private val verboseErrorTypes: Boolean,
|
private val options: DumpIrTreeOptions,
|
||||||
) : IrElementVisitor<String, Nothing?> {
|
) : IrElementVisitor<String, Nothing?> {
|
||||||
|
|
||||||
override fun visitElement(element: IrElement, data: Nothing?) = buildTrimEnd {
|
override fun visitElement(element: IrElement, data: Nothing?) = buildTrimEnd {
|
||||||
@@ -66,16 +66,16 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeParameter(declaration: IrTypeParameter, data: Nothing?): String =
|
override fun visitTypeParameter(declaration: IrTypeParameter, data: Nothing?): String =
|
||||||
renderTypeParameter(declaration, null, verboseErrorTypes)
|
renderTypeParameter(declaration, null, options)
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass, data: Nothing?) =
|
override fun visitClass(declaration: IrClass, data: Nothing?) =
|
||||||
renderClassWithRenderer(declaration, null, verboseErrorTypes)
|
renderClassWithRenderer(declaration, null, options)
|
||||||
|
|
||||||
override fun visitEnumEntry(declaration: IrEnumEntry, data: Nothing?) =
|
override fun visitEnumEntry(declaration: IrEnumEntry, data: Nothing?) =
|
||||||
renderEnumEntry(declaration)
|
renderEnumEntry(declaration)
|
||||||
|
|
||||||
override fun visitField(declaration: IrField, data: Nothing?) =
|
override fun visitField(declaration: IrField, data: Nothing?) =
|
||||||
renderField(declaration, null, verboseErrorTypes)
|
renderField(declaration, null, options)
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable, data: Nothing?) =
|
override fun visitVariable(declaration: IrVariable, data: Nothing?) =
|
||||||
buildTrimEnd {
|
buildTrimEnd {
|
||||||
@@ -83,7 +83,7 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
|
|
||||||
append(declaration.normalizedName(variableNameData))
|
append(declaration.normalizedName(variableNameData))
|
||||||
append(": ")
|
append(": ")
|
||||||
append(declaration.type.renderTypeWithRenderer(null, verboseErrorTypes))
|
append(declaration.type.renderTypeWithRenderer(null, options))
|
||||||
append(' ')
|
append(' ')
|
||||||
|
|
||||||
append(declaration.renderVariableFlags())
|
append(declaration.renderVariableFlags())
|
||||||
@@ -95,7 +95,7 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
buildTrimEnd {
|
buildTrimEnd {
|
||||||
append(declaration.name.asString())
|
append(declaration.name.asString())
|
||||||
append(": ")
|
append(": ")
|
||||||
append(declaration.type.renderTypeWithRenderer(null, verboseErrorTypes))
|
append(declaration.type.renderTypeWithRenderer(null, options))
|
||||||
append(' ')
|
append(' ')
|
||||||
|
|
||||||
append(declaration.renderValueParameterFlags())
|
append(declaration.renderValueParameterFlags())
|
||||||
@@ -130,17 +130,17 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
append("vararg ")
|
append("vararg ")
|
||||||
append(valueParameter.name.asString())
|
append(valueParameter.name.asString())
|
||||||
append(": ")
|
append(": ")
|
||||||
append(varargElementType.renderTypeWithRenderer(null, verboseErrorTypes))
|
append(varargElementType.renderTypeWithRenderer(null, options))
|
||||||
} else {
|
} else {
|
||||||
append(valueParameter.name.asString())
|
append(valueParameter.name.asString())
|
||||||
append(": ")
|
append(": ")
|
||||||
append(valueParameter.type.renderTypeWithRenderer(null, verboseErrorTypes))
|
append(valueParameter.type.renderTypeWithRenderer(null, options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration is IrSimpleFunction) {
|
if (declaration is IrSimpleFunction) {
|
||||||
append(": ")
|
append(": ")
|
||||||
append(declaration.renderReturnType(null, verboseErrorTypes))
|
append(declaration.renderReturnType(null, options))
|
||||||
}
|
}
|
||||||
append(' ')
|
append(' ')
|
||||||
|
|
||||||
@@ -173,10 +173,10 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
val getter = declaration.getter
|
val getter = declaration.getter
|
||||||
if (getter != null) {
|
if (getter != null) {
|
||||||
append(": ")
|
append(": ")
|
||||||
append(getter.renderReturnType(null, verboseErrorTypes))
|
append(getter.renderReturnType(null, options))
|
||||||
} else declaration.backingField?.type?.let { type ->
|
} else declaration.backingField?.type?.let { type ->
|
||||||
append(": ")
|
append(": ")
|
||||||
append(type.renderTypeWithRenderer(null, verboseErrorTypes))
|
append(type.renderTypeWithRenderer(null, options))
|
||||||
}
|
}
|
||||||
|
|
||||||
append(' ')
|
append(' ')
|
||||||
@@ -188,7 +188,7 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
if (declaration.isVar) append("var ") else append("val ")
|
if (declaration.isVar) append("var ") else append("val ")
|
||||||
append(declaration.name.asString())
|
append(declaration.name.asString())
|
||||||
append(": ")
|
append(": ")
|
||||||
append(declaration.type.renderTypeWithRenderer(null, verboseErrorTypes))
|
append(declaration.type.renderTypeWithRenderer(null, options))
|
||||||
append(" by (...)")
|
append(" by (...)")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +258,7 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
"name:$name visibility:$visibility modality:$modality " +
|
"name:$name visibility:$visibility modality:$modality " +
|
||||||
renderTypeParameters() + " " +
|
renderTypeParameters() + " " +
|
||||||
renderValueParameterTypes() + " " +
|
renderValueParameterTypes() + " " +
|
||||||
"returnType:${renderReturnType(this@RenderIrElementVisitor, verboseErrorTypes)} " +
|
"returnType:${renderReturnType(this@RenderIrElementVisitor, options)} " +
|
||||||
renderSimpleFunctionFlags()
|
renderSimpleFunctionFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
"visibility:$visibility " +
|
"visibility:$visibility " +
|
||||||
renderTypeParameters() + " " +
|
renderTypeParameters() + " " +
|
||||||
renderValueParameterTypes() + " " +
|
renderValueParameterTypes() + " " +
|
||||||
"returnType:${renderReturnType(this@RenderIrElementVisitor, verboseErrorTypes)} " +
|
"returnType:${renderReturnType(this@RenderIrElementVisitor, options)} " +
|
||||||
renderConstructorFlags()
|
renderConstructorFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,10 +287,10 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitField(declaration: IrField, data: Nothing?): String =
|
override fun visitField(declaration: IrField, data: Nothing?): String =
|
||||||
renderField(declaration, this, verboseErrorTypes)
|
renderField(declaration, this, options)
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass, data: Nothing?): String =
|
override fun visitClass(declaration: IrClass, data: Nothing?): String =
|
||||||
renderClassWithRenderer(declaration, this, verboseErrorTypes)
|
renderClassWithRenderer(declaration, this, options)
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable, data: Nothing?): String =
|
override fun visitVariable(declaration: IrVariable, data: Nothing?): String =
|
||||||
declaration.runTrimEnd {
|
declaration.runTrimEnd {
|
||||||
@@ -304,7 +304,7 @@ class RenderIrElementVisitor(normalizeNames: Boolean = false, private val verbos
|
|||||||
"ANONYMOUS_INITIALIZER isStatic=${declaration.isStatic}"
|
"ANONYMOUS_INITIALIZER isStatic=${declaration.isStatic}"
|
||||||
|
|
||||||
override fun visitTypeParameter(declaration: IrTypeParameter, data: Nothing?): String =
|
override fun visitTypeParameter(declaration: IrTypeParameter, data: Nothing?): String =
|
||||||
renderTypeParameter(declaration, this, verboseErrorTypes)
|
renderTypeParameter(declaration, this, options)
|
||||||
|
|
||||||
override fun visitValueParameter(declaration: IrValueParameter, data: Nothing?): String =
|
override fun visitValueParameter(declaration: IrValueParameter, data: Nothing?): String =
|
||||||
declaration.runTrimEnd {
|
declaration.runTrimEnd {
|
||||||
@@ -591,14 +591,15 @@ private fun IrDeclaration.renderDeclarationParentFqn(sb: StringBuilder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrType.render() = renderTypeWithRenderer(RenderIrElementVisitor(), true)
|
fun IrType.render(options: DumpIrTreeOptions = DumpIrTreeOptions()) =
|
||||||
|
renderTypeWithRenderer(RenderIrElementVisitor(options), options)
|
||||||
|
|
||||||
fun IrSimpleType.render() = (this as IrType).render()
|
fun IrSimpleType.render(options: DumpIrTreeOptions = DumpIrTreeOptions()) = (this as IrType).render(options)
|
||||||
|
|
||||||
fun IrTypeArgument.render() =
|
fun IrTypeArgument.render(options: DumpIrTreeOptions = DumpIrTreeOptions()) =
|
||||||
when (this) {
|
when (this) {
|
||||||
is IrStarProjection -> "*"
|
is IrStarProjection -> "*"
|
||||||
is IrTypeProjection -> "$variance ${type.render()}"
|
is IrTypeProjection -> "$variance ${type.render(options)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal inline fun <T, Buffer : Appendable> Buffer.appendIterableWith(
|
internal inline fun <T, Buffer : Appendable> Buffer.appendIterableWith(
|
||||||
@@ -726,17 +727,17 @@ private fun IrVariable.normalizedName(data: VariableNameData): String {
|
|||||||
return name.asString()
|
return name.asString()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.renderReturnType(renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean): String =
|
private fun IrFunction.renderReturnType(renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions): String =
|
||||||
safeReturnType?.renderTypeWithRenderer(renderer, verboseErrorTypes) ?: "<Uninitialized>"
|
safeReturnType?.renderTypeWithRenderer(renderer, options) ?: "<Uninitialized>"
|
||||||
|
|
||||||
private fun IrType.renderTypeWithRenderer(renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean): String =
|
private fun IrType.renderTypeWithRenderer(renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions): String =
|
||||||
"${renderTypeAnnotations(annotations, renderer, verboseErrorTypes)}${renderTypeInner(renderer, verboseErrorTypes)}"
|
"${renderTypeAnnotations(annotations, renderer, options)}${renderTypeInner(renderer, options)}"
|
||||||
|
|
||||||
private fun IrType.renderTypeInner(renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean) =
|
private fun IrType.renderTypeInner(renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions) =
|
||||||
when (this) {
|
when (this) {
|
||||||
is IrDynamicType -> "dynamic"
|
is IrDynamicType -> "dynamic"
|
||||||
|
|
||||||
is IrErrorType -> "IrErrorType(${verboseErrorTypes.ifTrue { originalKotlinType }})"
|
is IrErrorType -> "IrErrorType(${options.verboseErrorTypes.ifTrue { originalKotlinType }})"
|
||||||
|
|
||||||
is IrSimpleType -> buildTrimEnd {
|
is IrSimpleType -> buildTrimEnd {
|
||||||
val isDefinitelyNotNullType =
|
val isDefinitelyNotNullType =
|
||||||
@@ -746,7 +747,7 @@ private fun IrType.renderTypeInner(renderer: RenderIrElementVisitor?, verboseErr
|
|||||||
if (arguments.isNotEmpty()) {
|
if (arguments.isNotEmpty()) {
|
||||||
append(
|
append(
|
||||||
arguments.joinToString(prefix = "<", postfix = ">", separator = ", ") {
|
arguments.joinToString(prefix = "<", postfix = ">", separator = ", ") {
|
||||||
it.renderTypeArgument(renderer, verboseErrorTypes)
|
it.renderTypeArgument(renderer, options)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -756,22 +757,22 @@ private fun IrType.renderTypeInner(renderer: RenderIrElementVisitor?, verboseErr
|
|||||||
append('?')
|
append('?')
|
||||||
}
|
}
|
||||||
abbreviation?.let {
|
abbreviation?.let {
|
||||||
append(it.renderTypeAbbreviation(renderer, verboseErrorTypes))
|
append(it.renderTypeAbbreviation(renderer, options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> "{${javaClass.simpleName} $this}"
|
else -> "{${javaClass.simpleName} $this}"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrTypeAbbreviation.renderTypeAbbreviation(renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean): String =
|
private fun IrTypeAbbreviation.renderTypeAbbreviation(renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions): String =
|
||||||
buildString {
|
buildString {
|
||||||
append("{ ")
|
append("{ ")
|
||||||
append(renderTypeAnnotations(annotations, renderer, verboseErrorTypes))
|
append(renderTypeAnnotations(annotations, renderer, options))
|
||||||
append(typeAlias.renderTypeAliasFqn())
|
append(typeAlias.renderTypeAliasFqn())
|
||||||
if (arguments.isNotEmpty()) {
|
if (arguments.isNotEmpty()) {
|
||||||
append(
|
append(
|
||||||
arguments.joinToString(prefix = "<", postfix = ">", separator = ", ") {
|
arguments.joinToString(prefix = "<", postfix = ">", separator = ", ") {
|
||||||
it.renderTypeArgument(renderer, verboseErrorTypes)
|
it.renderTypeArgument(renderer, options)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -781,25 +782,25 @@ private fun IrTypeAbbreviation.renderTypeAbbreviation(renderer: RenderIrElementV
|
|||||||
append(" }")
|
append(" }")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrTypeArgument.renderTypeArgument(renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean): String =
|
private fun IrTypeArgument.renderTypeArgument(renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions): String =
|
||||||
when (this) {
|
when (this) {
|
||||||
is IrStarProjection -> "*"
|
is IrStarProjection -> "*"
|
||||||
|
|
||||||
is IrTypeProjection -> buildTrimEnd {
|
is IrTypeProjection -> buildTrimEnd {
|
||||||
append(variance.label)
|
append(variance.label)
|
||||||
if (variance != Variance.INVARIANT) append(' ')
|
if (variance != Variance.INVARIANT) append(' ')
|
||||||
append(type.renderTypeWithRenderer(renderer, verboseErrorTypes))
|
append(type.renderTypeWithRenderer(renderer, options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderTypeAnnotations(annotations: List<IrConstructorCall>, renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean) =
|
private fun renderTypeAnnotations(annotations: List<IrConstructorCall>, renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions) =
|
||||||
if (annotations.isEmpty())
|
if (annotations.isEmpty())
|
||||||
""
|
""
|
||||||
else
|
else
|
||||||
buildString {
|
buildString {
|
||||||
appendIterableWith(annotations, prefix = "", postfix = " ", separator = " ") {
|
appendIterableWith(annotations, prefix = "", postfix = " ", separator = " ") {
|
||||||
append("@[")
|
append("@[")
|
||||||
renderAsAnnotation(it, renderer, verboseErrorTypes)
|
renderAsAnnotation(it, renderer, options)
|
||||||
append("]")
|
append("]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -807,14 +808,14 @@ private fun renderTypeAnnotations(annotations: List<IrConstructorCall>, renderer
|
|||||||
private fun StringBuilder.renderAsAnnotation(
|
private fun StringBuilder.renderAsAnnotation(
|
||||||
irAnnotation: IrConstructorCall,
|
irAnnotation: IrConstructorCall,
|
||||||
renderer: RenderIrElementVisitor?,
|
renderer: RenderIrElementVisitor?,
|
||||||
verboseErrorTypes: Boolean,
|
options: DumpIrTreeOptions,
|
||||||
) {
|
) {
|
||||||
val annotationClassName = irAnnotation.symbol.takeIf { it.isBound }?.owner?.parentAsClass?.name?.asString() ?: "<unbound>"
|
val annotationClassName = irAnnotation.symbol.takeIf { it.isBound }?.owner?.parentAsClass?.name?.asString() ?: "<unbound>"
|
||||||
append(annotationClassName)
|
append(annotationClassName)
|
||||||
|
|
||||||
if (irAnnotation.typeArgumentsCount != 0) {
|
if (irAnnotation.typeArgumentsCount != 0) {
|
||||||
(0 until irAnnotation.typeArgumentsCount).joinTo(this, ", ", "<", ">") { i ->
|
(0 until irAnnotation.typeArgumentsCount).joinTo(this, ", ", "<", ">") { i ->
|
||||||
irAnnotation.getTypeArgument(i)?.renderTypeWithRenderer(renderer, verboseErrorTypes) ?: "null"
|
irAnnotation.getTypeArgument(i)?.renderTypeWithRenderer(renderer, options) ?: "null"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -825,14 +826,14 @@ private fun StringBuilder.renderAsAnnotation(
|
|||||||
appendIterableWith(0 until irAnnotation.valueArgumentsCount, separator = ", ", prefix = "(", postfix = ")") {
|
appendIterableWith(0 until irAnnotation.valueArgumentsCount, separator = ", ", prefix = "(", postfix = ")") {
|
||||||
append(valueParameterNames[it])
|
append(valueParameterNames[it])
|
||||||
append(" = ")
|
append(" = ")
|
||||||
renderAsAnnotationArgument(irAnnotation.getValueArgument(it), renderer, verboseErrorTypes)
|
renderAsAnnotationArgument(irAnnotation.getValueArgument(it), renderer, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun StringBuilder.renderAsAnnotationArgument(irElement: IrElement?, renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean) {
|
private fun StringBuilder.renderAsAnnotationArgument(irElement: IrElement?, renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions) {
|
||||||
when (irElement) {
|
when (irElement) {
|
||||||
null -> append("<null>")
|
null -> append("<null>")
|
||||||
is IrConstructorCall -> renderAsAnnotation(irElement, renderer, verboseErrorTypes)
|
is IrConstructorCall -> renderAsAnnotation(irElement, renderer, options)
|
||||||
is IrConst<*> -> {
|
is IrConst<*> -> {
|
||||||
append('\'')
|
append('\'')
|
||||||
append(irElement.value.toString())
|
append(irElement.value.toString())
|
||||||
@@ -840,7 +841,7 @@ private fun StringBuilder.renderAsAnnotationArgument(irElement: IrElement?, rend
|
|||||||
}
|
}
|
||||||
is IrVararg -> {
|
is IrVararg -> {
|
||||||
appendIterableWith(irElement.elements, prefix = "[", postfix = "]", separator = ", ") {
|
appendIterableWith(irElement.elements, prefix = "[", postfix = "]", separator = ", ") {
|
||||||
renderAsAnnotationArgument(it, renderer, verboseErrorTypes)
|
renderAsAnnotationArgument(it, renderer, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> if (renderer != null) {
|
else -> if (renderer != null) {
|
||||||
@@ -851,35 +852,35 @@ private fun StringBuilder.renderAsAnnotationArgument(irElement: IrElement?, rend
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderClassWithRenderer(declaration: IrClass, renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean) =
|
private fun renderClassWithRenderer(declaration: IrClass, renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions) =
|
||||||
declaration.runTrimEnd {
|
declaration.runTrimEnd {
|
||||||
"CLASS ${renderOriginIfNonTrivial()}" +
|
"CLASS ${renderOriginIfNonTrivial()}" +
|
||||||
"$kind name:$name modality:$modality visibility:$visibility " +
|
"$kind name:$name modality:$modality visibility:$visibility " +
|
||||||
renderClassFlags() +
|
renderClassFlags() +
|
||||||
"superTypes:[${superTypes.joinToString(separator = "; ") { it.renderTypeWithRenderer(renderer, verboseErrorTypes) }}]"
|
"superTypes:[${superTypes.joinToString(separator = "; ") { it.renderTypeWithRenderer(renderer, options) }}]"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderEnumEntry(declaration: IrEnumEntry) = declaration.runTrimEnd {
|
private fun renderEnumEntry(declaration: IrEnumEntry) = declaration.runTrimEnd {
|
||||||
"ENUM_ENTRY ${renderOriginIfNonTrivial()}name:$name"
|
"ENUM_ENTRY ${renderOriginIfNonTrivial()}name:$name"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderField(declaration: IrField, renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean) = declaration.runTrimEnd {
|
private fun renderField(declaration: IrField, renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions) = declaration.runTrimEnd {
|
||||||
"FIELD ${renderOriginIfNonTrivial()}name:$name type:${
|
"FIELD ${renderOriginIfNonTrivial()}name:$name type:${
|
||||||
type.renderTypeWithRenderer(
|
type.renderTypeWithRenderer(
|
||||||
renderer,
|
renderer,
|
||||||
verboseErrorTypes
|
options
|
||||||
)
|
)
|
||||||
} visibility:$visibility ${renderFieldFlags()}"
|
} visibility:$visibility ${renderFieldFlags()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderTypeParameter(declaration: IrTypeParameter, renderer: RenderIrElementVisitor?, verboseErrorTypes: Boolean) =
|
private fun renderTypeParameter(declaration: IrTypeParameter, renderer: RenderIrElementVisitor?, options: DumpIrTreeOptions) =
|
||||||
declaration.runTrimEnd {
|
declaration.runTrimEnd {
|
||||||
"TYPE_PARAMETER ${renderOriginIfNonTrivial()}" +
|
"TYPE_PARAMETER ${renderOriginIfNonTrivial()}" +
|
||||||
"name:$name index:$index variance:$variance " +
|
"name:$name index:$index variance:$variance " +
|
||||||
"superTypes:[${
|
"superTypes:[${
|
||||||
superTypes.joinToString(separator = "; ") {
|
superTypes.joinToString(separator = "; ") {
|
||||||
it.renderTypeWithRenderer(
|
it.renderTypeWithRenderer(
|
||||||
renderer, verboseErrorTypes
|
renderer, options
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}] " +
|
}] " +
|
||||||
|
|||||||
+3
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
|||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.util.DumpIrTreeOptions
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
import org.jetbrains.kotlin.ir.util.dumpTreesFromLineNumber
|
import org.jetbrains.kotlin.ir.util.dumpTreesFromLineNumber
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -67,9 +68,9 @@ class IrTextDumpHandler(testServices: TestServices) : AbstractIrHandler(testServ
|
|||||||
|
|
||||||
for ((testFile, irFile) in testFileToIrFile) {
|
for ((testFile, irFile) in testFileToIrFile) {
|
||||||
if (testFile?.directives?.contains(EXTERNAL_FILE) == true) continue
|
if (testFile?.directives?.contains(EXTERNAL_FILE) == true) continue
|
||||||
var actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true)
|
var actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, DumpIrTreeOptions(normalizeNames = true))
|
||||||
if (actualDump.isEmpty()) {
|
if (actualDump.isEmpty()) {
|
||||||
actualDump = irFile.dumpTreesFromLineNumber(lineNumber = UNDEFINED_OFFSET, normalizeNames = true)
|
actualDump = irFile.dumpTreesFromLineNumber(lineNumber = UNDEFINED_OFFSET, DumpIrTreeOptions(normalizeNames = true))
|
||||||
}
|
}
|
||||||
builder.append(actualDump)
|
builder.append(actualDump)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.test.backend.handlers
|
package org.jetbrains.kotlin.test.backend.handlers
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrVerifier
|
import org.jetbrains.kotlin.ir.IrVerifier
|
||||||
|
import org.jetbrains.kotlin.ir.util.DumpIrTreeOptions
|
||||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||||
import org.jetbrains.kotlin.ir.util.dumpTreesFromLineNumber
|
import org.jetbrains.kotlin.ir.util.dumpTreesFromLineNumber
|
||||||
import org.jetbrains.kotlin.test.backend.handlers.IrTextDumpHandler.Companion.groupWithTestFiles
|
import org.jetbrains.kotlin.test.backend.handlers.IrTextDumpHandler.Companion.groupWithTestFiles
|
||||||
@@ -32,10 +33,10 @@ class IrTreeVerifierHandler(testServices: TestServices) : AbstractIrHandler(test
|
|||||||
|
|
||||||
IrVerifier(assertions, module.frontendKind == FrontendKinds.FIR).verifyWithAssert(irFile)
|
IrVerifier(assertions, module.frontendKind == FrontendKinds.FIR).verifyWithAssert(irFile)
|
||||||
|
|
||||||
val actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true)
|
val actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, DumpIrTreeOptions(normalizeNames = true))
|
||||||
|
|
||||||
val irFileCopy = irFile.deepCopyWithSymbols()
|
val irFileCopy = irFile.deepCopyWithSymbols()
|
||||||
val dumpOfCopy = irFileCopy.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true)
|
val dumpOfCopy = irFileCopy.dumpTreesFromLineNumber(lineNumber = 0, DumpIrTreeOptions(normalizeNames = true))
|
||||||
assertions.assertEquals(actualDump, dumpOfCopy) { "IR dump mismatch after deep copy with symbols" }
|
assertions.assertEquals(actualDump, dumpOfCopy) { "IR dump mismatch after deep copy with symbols" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,14 +96,14 @@ abstract class AbstractKlibIrTextTestCase : CodegenTestCase() {
|
|||||||
val ignoreErrors = AbstractIrGeneratorTestCase.shouldIgnoreErrors(wholeFile)
|
val ignoreErrors = AbstractIrGeneratorTestCase.shouldIgnoreErrors(wholeFile)
|
||||||
val stdlib = loadKlibFromPath(listOf(runtimeKlibPath)).single()
|
val stdlib = loadKlibFromPath(listOf(runtimeKlibPath)).single()
|
||||||
val (irModule, bindingContext) = buildFragmentAndLinkIt(stdlib, ignoreErrors, expectActualSymbols)
|
val (irModule, bindingContext) = buildFragmentAndLinkIt(stdlib, ignoreErrors, expectActualSymbols)
|
||||||
val expected = irModule.dump(stableOrder = true)
|
val expected = irModule.dump(DumpIrTreeOptions(stableOrder = true, verboseErrorTypes = false))
|
||||||
val mppProject =
|
val mppProject =
|
||||||
myEnvironment.configuration.languageVersionSettings.getFeatureSupport(LanguageFeature.MultiPlatformProjects) == LanguageFeature.State.ENABLED
|
myEnvironment.configuration.languageVersionSettings.getFeatureSupport(LanguageFeature.MultiPlatformProjects) == LanguageFeature.State.ENABLED
|
||||||
val klibPath = serializeModule(irModule, bindingContext, stdlib, ignoreErrors, expectActualSymbols, !mppProject)
|
val klibPath = serializeModule(irModule, bindingContext, stdlib, ignoreErrors, expectActualSymbols, !mppProject)
|
||||||
val libs = loadKlibFromPath(listOf(runtimeKlibPath, klibPath))
|
val libs = loadKlibFromPath(listOf(runtimeKlibPath, klibPath))
|
||||||
val (stdlib2, klib) = libs
|
val (stdlib2, klib) = libs
|
||||||
val deserializedIrModule = deserializeModule(stdlib2, klib)
|
val deserializedIrModule = deserializeModule(stdlib2, klib)
|
||||||
val actual = deserializedIrModule.dump(stableOrder = true)
|
val actual = deserializedIrModule.dump(DumpIrTreeOptions(stableOrder = true, verboseErrorTypes = false))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
TestCase.assertEquals(wholeFile.name, expected, actual)
|
TestCase.assertEquals(wholeFile.name, expected, actual)
|
||||||
|
|||||||
Reference in New Issue
Block a user