[IR] Support stable order in IR dump

That mode is need to test deserialization of klibs
This commit is contained in:
Roman Artemev
2021-06-07 16:12:29 +03:00
committed by teamcityserver
parent bbcd511c44
commit 2eac442705
2 changed files with 37 additions and 8 deletions
@@ -16,8 +16,8 @@
package org.jetbrains.kotlin.ir.util package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.ir.IrFileEntry
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
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
@@ -27,10 +27,10 @@ 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): String = fun IrElement.dump(normalizeNames: Boolean = false, stableOrder: Boolean = false): String =
try { try {
StringBuilder().also { sb -> StringBuilder().also { sb ->
accept(DumpIrTreeVisitor(sb, normalizeNames), "") accept(DumpIrTreeVisitor(sb, normalizeNames, stableOrder), "")
}.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()
@@ -44,13 +44,42 @@ fun IrFile.dumpTreesFromLineNumber(lineNumber: Int, normalizeNames: Boolean = fa
class DumpIrTreeVisitor( class DumpIrTreeVisitor(
out: Appendable, out: Appendable,
normalizeNames: Boolean = false normalizeNames: Boolean = false,
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) private val elementRenderer = RenderIrElementVisitor(normalizeNames)
private fun IrType.render() = elementRenderer.renderType(this) private fun IrType.render() = elementRenderer.renderType(this)
private fun List<IrDeclaration>.ordered(): List<IrDeclaration> {
if (!stableOrder) return this
val strictOrder = mutableMapOf<IrDeclaration, Int>()
var idx = 0
forEach {
if (it is IrProperty && it.backingField != null && !it.isConst) {
strictOrder[it] = idx++
}
if (it is IrAnonymousInitializer) {
strictOrder[it] = idx++
}
}
return sortedWith { a, b ->
val strictA = strictOrder[a] ?: Int.MAX_VALUE
val strictB = strictOrder[b] ?: Int.MAX_VALUE
if (strictA == strictB) {
val rA = a.render()
val rB = b.render()
rA.compareTo(rB)
} else strictA - strictB
}
}
override fun visitElement(element: IrElement, data: String) { override fun visitElement(element: IrElement, data: String) {
element.dumpLabeledElementWith(data) { element.dumpLabeledElementWith(data) {
if (element is IrAnnotationContainer) { if (element is IrAnnotationContainer) {
@@ -69,7 +98,7 @@ class DumpIrTreeVisitor(
override fun visitFile(declaration: IrFile, data: String) { override fun visitFile(declaration: IrFile, data: String) {
declaration.dumpLabeledElementWith(data) { declaration.dumpLabeledElementWith(data) {
dumpAnnotations(declaration) dumpAnnotations(declaration)
declaration.declarations.dumpElements() declaration.declarations.ordered().dumpElements()
} }
} }
@@ -78,7 +107,7 @@ class DumpIrTreeVisitor(
dumpAnnotations(declaration) dumpAnnotations(declaration)
declaration.thisReceiver?.accept(this, "\$this") declaration.thisReceiver?.accept(this, "\$this")
declaration.typeParameters.dumpElements() declaration.typeParameters.dumpElements()
declaration.declarations.dumpElements() declaration.declarations.ordered().dumpElements()
} }
} }
@@ -83,7 +83,7 @@ abstract class AbstractKlibTextTestCase : 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() val expected = irModule.dump(stableOrder = true)
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)
@@ -91,7 +91,7 @@ abstract class AbstractKlibTextTestCase : CodegenTestCase() {
val stdlib2 = libs[0] val stdlib2 = libs[0]
val klib = libs[1] val klib = libs[1]
val deserializedIrModule = deserializeModule(stdlib2, klib) val deserializedIrModule = deserializeModule(stdlib2, klib)
val actual = deserializedIrModule.dump() val actual = deserializedIrModule.dump(stableOrder = true)
try { try {
TestCase.assertEquals(wholeFile.name, expected, actual) TestCase.assertEquals(wholeFile.name, expected, actual)