From b22e89e91d20e7553f33fd1a03fb58391f0a817d Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Mon, 8 May 2023 17:07:17 +0200 Subject: [PATCH] [Tests] Consider dependent fragments in IR handlers --- .../multiplatform/expectedEnumClass2.ir.txt | 59 +++++++++++++++++++ .../multiplatform/expectedEnumClass2.kt.txt | 20 +++++++ .../test/backend/handlers/HandlerUtils.kt | 18 ++++++ .../backend/handlers/IrInlineBodiesHandler.kt | 8 ++- .../handlers/IrInterpreterBackendHandler.kt | 9 +-- .../handlers/IrPrettyKotlinDumpHandler.kt | 30 +++++----- .../backend/handlers/IrTextDumpHandler.kt | 22 ++++--- .../backend/handlers/IrTreeVerifierHandler.kt | 21 ++++--- .../test/utils/MultiModuleInfoDumper.kt | 12 ++-- 9 files changed, 155 insertions(+), 44 deletions(-) create mode 100644 compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/HandlerUtils.kt diff --git a/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass2.ir.txt b/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass2.ir.txt index 512ceba8c70..a81cfd136b4 100644 --- a/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass2.ir.txt +++ b/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass2.ir.txt @@ -1,3 +1,62 @@ +Module: +FILE fqName: fileName:/lib.kt + CLASS ENUM_CLASS name:MyEnum modality:FINAL visibility:public [expect] superTypes:[kotlin.Enum<.MyEnum>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.MyEnum + CONSTRUCTOR visibility:private <> () returnType:.MyEnum [primary,expect] + ENUM_ENTRY name:FOO + init: EXPRESSION_BODY + ENUM_CONSTRUCTOR_CALL 'private constructor () [primary,expect] declared in .MyEnum' + ENUM_ENTRY name:BAR + init: EXPRESSION_BODY + ENUM_CONSTRUCTOR_CALL 'private constructor () [primary,expect] declared in .MyEnum' + FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<.MyEnum> [expect] + FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:.MyEnum [expect] + VALUE_PARAMETER name:value index:0 type:kotlin.String + PROPERTY ENUM_CLASS_SPECIAL_MEMBER name:entries visibility:public modality:FINAL [expect,val] + FUN ENUM_CLASS_SPECIAL_MEMBER name: visibility:public modality:FINAL <> () returnType:kotlin.enums.EnumEntries<.MyEnum> + correspondingProperty: PROPERTY ENUM_CLASS_SPECIAL_MEMBER name:entries visibility:public modality:FINAL [expect,val] + SYNTHETIC_BODY kind=ENUM_ENTRIES + FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Any [expect,fake_override] + overridden: + protected final fun clone (): kotlin.Any declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum, other:.MyEnum) returnType:kotlin.Int [expect,fake_override,operator] + overridden: + public final fun compareTo (other: E of kotlin.Enum): kotlin.Int [operator] declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + VALUE_PARAMETER name:other index:0 type:.MyEnum + FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum, other:kotlin.Any?) returnType:kotlin.Boolean [expect,fake_override,operator] + overridden: + public final fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [expect,fake_override] + overridden: + public final fun hashCode (): kotlin.Int declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum) returnType:kotlin.String [expect,fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [expect,fake_override,val] + annotations: + IntrinsicConstEvaluation + overridden: + public final name: kotlin.String [val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.String [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [expect,fake_override,val] + overridden: + public final fun (): kotlin.String declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [expect,fake_override,val] + overridden: + public final ordinal: kotlin.Int [val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [expect,fake_override,val] + overridden: + public final fun (): kotlin.Int declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum +Module: main FILE fqName: fileName:/main.kt CLASS ENUM_CLASS name:MyEnum modality:FINAL visibility:public superTypes:[kotlin.Enum<.MyEnum>] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.MyEnum diff --git a/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass2.kt.txt b/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass2.kt.txt index 00d8f6767e2..26c3c67bcec 100644 --- a/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass2.kt.txt +++ b/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass2.kt.txt @@ -1,3 +1,22 @@ +// MODULE: +// FILE: lib.kt + +expect enum class MyEnum : Enum { + private expect constructor() /* primary */ + FOO = MyEnum() + + BAR = MyEnum() + + expect fun values(): Array + + expect fun valueOf(value: String): MyEnum + + expect val entries: EnumEntries + get(): EnumEntries /* Synthetic body for ENUM_ENTRIES */ + +} + +// MODULE: main // FILE: main.kt enum class MyEnum : Enum { @@ -21,3 +40,4 @@ enum class MyEnum : Enum { get(): EnumEntries /* Synthetic body for ENUM_ENTRIES */ } + diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/HandlerUtils.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/HandlerUtils.kt new file mode 100644 index 00000000000..1240aebddde --- /dev/null +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/HandlerUtils.kt @@ -0,0 +1,18 @@ +/* + * 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.test.backend.handlers + +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.test.backend.ir.IrBackendInput +import org.jetbrains.kotlin.test.model.TestModule + +inline fun IrBackendInput.processAllIrModuleFragments( + module: TestModule, + processor: (irModuleFragment: IrModuleFragment, moduleName: String) -> Unit +) { + dependentIrModuleFragments.forEach { processor(it, it.name.asString()) } + processor(irModuleFragment, module.name) +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt index 52e07c50fc6..30fb0bb7db7 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt @@ -23,9 +23,11 @@ class IrInlineBodiesHandler(testServices: TestServices) : AbstractIrHandler(test val declaredInlineFunctionSignatures = mutableSetOf() override fun processModule(module: TestModule, info: IrBackendInput) { - val irModule = info.irModuleFragment - irModule.acceptChildrenVoid(InlineFunctionsCollector()) - irModule.acceptChildrenVoid(InlineCallBodiesCheck()) + info.processAllIrModuleFragments(module) { irModule, _ -> + irModule.acceptChildrenVoid(InlineFunctionsCollector()) + irModule.acceptChildrenVoid(InlineCallBodiesCheck()) + } + assertions.assertTrue((info as IrBackendInput.JvmIrBackendInput).backendInput.symbolTable.allUnbound.isEmpty()) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInterpreterBackendHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInterpreterBackendHandler.kt index 3a1777e7424..8ec0ef731f2 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInterpreterBackendHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInterpreterBackendHandler.kt @@ -37,10 +37,11 @@ open class IrInterpreterBackendHandler(testServices: TestServices) : AbstractIrH override fun processAfterAllModules(someAssertionWasFailed: Boolean) {} override fun processModule(module: TestModule, info: IrBackendInput) { - val moduleFragment = info.irModuleFragment - val evaluator = Evaluator(IrInterpreter(moduleFragment.irBuiltins), globalMetadataInfoHandler) - for ((irFile, testFile) in matchIrFileWithTestFile(moduleFragment, module)) { - evaluator.evaluate(irFile, testFile) + info.processAllIrModuleFragments(module) { moduleFragment, _ -> + val evaluator = Evaluator(IrInterpreter(moduleFragment.irBuiltins), globalMetadataInfoHandler) + for ((irFile, testFile) in matchIrFileWithTestFile(moduleFragment, module)) { + evaluator.evaluate(irFile, testFile) + } } } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrPrettyKotlinDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrPrettyKotlinDumpHandler.kt index 8a324bf27d7..ac9dd3a8a8c 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrPrettyKotlinDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrPrettyKotlinDumpHandler.kt @@ -36,21 +36,23 @@ class IrPrettyKotlinDumpHandler(testServices: TestServices) : AbstractIrHandler( override fun processModule(module: TestModule, info: IrBackendInput) { if (DUMP_KT_IR !in module.directives || SKIP_KT_DUMP in module.directives) return - val irFiles = info.irModuleFragment.files - val builder = dumper.builderForModule(module) - val filteredIrFiles = irFiles.groupWithTestFiles(module).filterNot { - it.first?.directives?.contains(EXTERNAL_FILE) == true - }.map { it.second } - val printFileName = filteredIrFiles.size > 1 || testServices.moduleStructure.modules.size > 1 - for (irFile in filteredIrFiles) { - val dump = irFile.dumpKotlinLike( - KotlinLikeDumpOptions( - printFileName = printFileName, - printFilePath = false, - printFakeOverridesStrategy = FakeOverridesStrategy.NONE + info.processAllIrModuleFragments(module) { irModuleFragment, moduleName -> + val irFiles = irModuleFragment.files + val builder = dumper.builderForModule(moduleName) + val filteredIrFiles = irFiles.groupWithTestFiles(module).filterNot { + it.first?.directives?.contains(EXTERNAL_FILE) == true + }.map { it.second } + val printFileName = filteredIrFiles.size > 1 || testServices.moduleStructure.modules.size > 1 + for (irFile in filteredIrFiles) { + val dump = irFile.dumpKotlinLike( + KotlinLikeDumpOptions( + printFileName = printFileName, + printFilePath = false, + printFakeOverridesStrategy = FakeOverridesStrategy.NONE + ) ) - ) - builder.append(dump) + builder.append(dump) + } } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTextDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTextDumpHandler.kt index 8eaa2bbecd2..0316273effa 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTextDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTextDumpHandler.kt @@ -60,17 +60,21 @@ class IrTextDumpHandler(testServices: TestServices) : AbstractIrHandler(testServ override fun processModule(module: TestModule, info: IrBackendInput) { if (DUMP_IR !in module.directives) return - val irFiles = info.irModuleFragment.files - val testFileToIrFile = irFiles.groupWithTestFiles(module) - val builder = baseDumper.builderForModule(module) - for ((testFile, irFile) in testFileToIrFile) { - if (testFile?.directives?.contains(EXTERNAL_FILE) == true) continue - var actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true) - if (actualDump.isEmpty()) { - actualDump = irFile.dumpTreesFromLineNumber(lineNumber = UNDEFINED_OFFSET, normalizeNames = true) + + info.processAllIrModuleFragments(module) { irModuleFragment, moduleName -> + val builder = baseDumper.builderForModule(moduleName) + val testFileToIrFile = irModuleFragment.files.groupWithTestFiles(module) + + for ((testFile, irFile) in testFileToIrFile) { + if (testFile?.directives?.contains(EXTERNAL_FILE) == true) continue + var actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true) + if (actualDump.isEmpty()) { + actualDump = irFile.dumpTreesFromLineNumber(lineNumber = UNDEFINED_OFFSET, normalizeNames = true) + } + builder.append(actualDump) } - builder.append(actualDump) } + compareDumpsOfExternalClasses(module, info) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTreeVerifierHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTreeVerifierHandler.kt index d746461c974..19e4d1e78c1 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTreeVerifierHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTreeVerifierHandler.kt @@ -23,18 +23,21 @@ class IrTreeVerifierHandler(testServices: TestServices) : AbstractIrHandler(test override fun processModule(module: TestModule, info: IrBackendInput) { if (CodegenTestDirectives.DUMP_IR !in module.directives) return - val irFiles = info.irModuleFragment.files - val testFileToIrFile = irFiles.groupWithTestFiles(module) - for ((testFile, irFile) in testFileToIrFile) { - if (testFile?.directives?.contains(EXTERNAL_FILE) == true) continue - IrVerifier(assertions, module.frontendKind == FrontendKinds.FIR).verifyWithAssert(irFile) + info.processAllIrModuleFragments(module) { irModuleFragment, _ -> + val irFiles = irModuleFragment.files + val testFileToIrFile = irFiles.groupWithTestFiles(module) + for ((testFile, irFile) in testFileToIrFile) { + if (testFile?.directives?.contains(EXTERNAL_FILE) == true) continue - val actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true) + IrVerifier(assertions, module.frontendKind == FrontendKinds.FIR).verifyWithAssert(irFile) - val irFileCopy = irFile.deepCopyWithSymbols() - val dumpOfCopy = irFileCopy.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true) - assertions.assertEquals(actualDump, dumpOfCopy) { "IR dump mismatch after deep copy with symbols" } + val actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true) + + val irFileCopy = irFile.deepCopyWithSymbols() + val dumpOfCopy = irFileCopy.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true) + assertions.assertEquals(actualDump, dumpOfCopy) { "IR dump mismatch after deep copy with symbols" } + } } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/utils/MultiModuleInfoDumper.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/utils/MultiModuleInfoDumper.kt index 145dea0026b..d2b17620186 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/utils/MultiModuleInfoDumper.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/utils/MultiModuleInfoDumper.kt @@ -9,10 +9,12 @@ import org.jetbrains.kotlin.test.model.TestModule // TODO: consider about tests with multiple testdata files class MultiModuleInfoDumper(private val moduleHeaderTemplate: String? = "Module: %s") { - private val builderByModule = LinkedHashMap() + private val builderByModule = LinkedHashMap() - fun builderForModule(module: TestModule): StringBuilder { - return builderByModule.getOrPut(module, ::StringBuilder) + fun builderForModule(module: TestModule): StringBuilder = builderForModule(module.name) + + fun builderForModule(moduleName: String): StringBuilder { + return builderByModule.getOrPut(moduleName, ::StringBuilder) } fun generateResultingDump(): String { @@ -21,8 +23,8 @@ class MultiModuleInfoDumper(private val moduleHeaderTemplate: String? = "Module: return it.toString() } return buildString { - for ((module, builder) in builderByModule) { - moduleHeaderTemplate?.let { appendLine(String.format(it, module.name)) } + for ((moduleName, builder) in builderByModule) { + moduleHeaderTemplate?.let { appendLine(String.format(it, moduleName)) } append(builder) } addNewLineIfNeeded()