From 7dbfe4bfb1fc66ea080317fd57ea3d9a65b6f170 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Fri, 11 Aug 2023 22:51:21 +0200 Subject: [PATCH] [IR][tests] Fix MPP IR dump tests to not fail on missing expect declarations Expect declarations do not survive serialization to KLIB. So they need to be explicitly filtered in order for tests that compare dumped IR before and after serialization to pass successfully. ^KT-61136 --- .../kotlin/klib/AbstractKlibIrTextTestCase.kt | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/klib/AbstractKlibIrTextTestCase.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/klib/AbstractKlibIrTextTestCase.kt index 1a5debf02a7..8eb1fc87a92 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/klib/AbstractKlibIrTextTestCase.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/klib/AbstractKlibIrTextTestCase.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import junit.framework.TestCase import org.jetbrains.kotlin.backend.common.CommonKLibResolver +import org.jetbrains.kotlin.backend.common.ir.isExpect import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode @@ -25,16 +26,18 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.ir.AbstractIrGeneratorTestCase +import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.backend.js.JsFactories import org.jetbrains.kotlin.ir.backend.js.KotlinFileSerializedData import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS import org.jetbrains.kotlin.library.* import org.jetbrains.kotlin.library.impl.BuiltInsPlatform @@ -94,15 +97,20 @@ abstract class AbstractKlibIrTextTestCase : CodegenTestCase() { fun doTest(wholeFile: File) { val expectActualSymbols = mutableMapOf() val ignoreErrors = AbstractIrGeneratorTestCase.shouldIgnoreErrors(wholeFile) + val stdlib = loadKlibFromPath(listOf(runtimeKlibPath)).single() - val (irModule, bindingContext) = buildFragmentAndLinkIt(stdlib, ignoreErrors, expectActualSymbols) + val (irModule, bindingContext) = generateIrModule(stdlib, ignoreErrors, expectActualSymbols) + irModule.cleanUpFromExpectDeclarations() + val expected = irModule.dump(DumpIrTreeOptions(stableOrder = true, verboseErrorTypes = false)) + val mppProject = myEnvironment.configuration.languageVersionSettings.getFeatureSupport(LanguageFeature.MultiPlatformProjects) == LanguageFeature.State.ENABLED val klibPath = serializeModule(irModule, bindingContext, stdlib, ignoreErrors, expectActualSymbols, !mppProject) val libs = loadKlibFromPath(listOf(runtimeKlibPath, klibPath)) val (stdlib2, klib) = libs val deserializedIrModule = deserializeModule(stdlib2, klib) + val actual = deserializedIrModule.dump(DumpIrTreeOptions(stableOrder = true, verboseErrorTypes = false)) try { @@ -242,8 +250,28 @@ abstract class AbstractKlibIrTextTestCase : CodegenTestCase() { private val runtimeKlibPath = "libraries/stdlib/build/classes/kotlin/js/main" - private fun buildFragmentAndLinkIt(stdlib: KotlinLibrary, ignoreErrors: Boolean, expectActualSymbols: MutableMap): Pair { - return generateIrModule(stdlib, ignoreErrors, expectActualSymbols) + /** + * In multiplatform projects there may be `expect` declarations. Such declarations do not survive during KLIB serialization. + * So, it's necessary to explicitly filter them out from the [IrModuleFragment] in order for tests that compare dumped IR + * before and after serialization to pass successfully. + */ + private fun IrModuleFragment.cleanUpFromExpectDeclarations() { + val languageVersionSettings = myEnvironment.configuration.languageVersionSettings + val multiPlatformProjects = languageVersionSettings.getFeatureSupport(LanguageFeature.MultiPlatformProjects) + if (multiPlatformProjects != LanguageFeature.State.ENABLED) + return + + acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) = element.acceptChildrenVoid(this) + + override fun visitPackageFragment(declaration: IrPackageFragment) = visitDeclarationContainer(declaration) + override fun visitClass(declaration: IrClass) = visitDeclarationContainer(declaration) + + private fun visitDeclarationContainer(container: IrDeclarationContainer) { + container.declarations.removeIf(IrDeclaration::isExpect) + visitElement(container) + } + }) } fun getModuleDescriptor(current: KotlinLibrary, builtins: ModuleDescriptorImpl? = null): ModuleDescriptorImpl {