From 522952db1f8a5a7a956ec2815cc86a25a5384e7e Mon Sep 17 00:00:00 2001 From: Alexander Korepanov Date: Thu, 7 Sep 2023 22:08:22 +0200 Subject: [PATCH] [JS IR] Run diagnostics by IR before the klib serialization Implement an infrastructure for checking IR before JS klib serialization. Implement the EXPORTING_JS_NAME_CLASH and EXPORTING_JS_NAME_CLASH_ES checks. ^KT-61710 Fixed --- .../jetbrains/kotlin/cli/js/K2JsIrCompiler.kt | 14 +++++ .../kotlin/cli/js/klib/compilerPipeline.kt | 14 ++++- .../ir/backend/js/checkers/JsKlibCheckers.kt | 37 ++++++++++++ .../js/checkers/JsKlibDeclarationsChecker.kt | 14 +++++ .../ir/backend/js/checkers/JsKlibErrors.kt | 47 +++++++++++++++ .../js/checkers/JsKlibExportingDeclaration.kt | 57 +++++++++++++++++++ .../JsKlibEsModuleExportsChecker.kt | 28 +++++++++ .../JsKlibOtherModuleExportsChecker.kt | 55 ++++++++++++++++++ .../jetbrains/kotlin/ir/backend/js/klib.kt | 48 ++++++---------- .../lower/serialization/ir/JsExportUtils.kt | 48 ++++++++++++++++ .../serialization/ir/JsIrFileMetadata.kt | 3 +- .../serialization/ir/JsIrFileSerializer.kt | 53 ++++------------- .../serialization/ir/JsIrModuleSerializer.kt | 6 +- .../multiplatform/jsNameClash/output.txt | 6 ++ .../optionalExpectation/output.txt | 3 + .../testData/multiplatform/simple/output.txt | 6 ++ .../kotlin/klib/FilePathsInKlibTest.kt | 5 +- .../kotlin/benchmarks/GenerateIrRuntime.kt | 4 ++ .../incremental/IrAbstractInvalidationTest.kt | 5 +- .../test/converters/FirJsKlibBackendFacade.kt | 1 + .../js/test/converters/JsKlibBackendFacade.kt | 1 + .../ir/AbstractJsPartialLinkageTestCase.kt | 11 +++- .../kotlin/gradle/Kotlin2JsGradlePluginIT.kt | 5 +- .../converters/FirWasmKlibBackendFacade.kt | 1 + 24 files changed, 385 insertions(+), 87 deletions(-) create mode 100644 compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibCheckers.kt create mode 100644 compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibDeclarationsChecker.kt create mode 100644 compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibErrors.kt create mode 100644 compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibExportingDeclaration.kt create mode 100644 compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/declarations/JsKlibEsModuleExportsChecker.kt create mode 100644 compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/declarations/JsKlibOtherModuleExportsChecker.kt create mode 100644 compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsExportUtils.kt diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt index c258a4e1498..76eb293e083 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.RUNTIME_DIAGNOSTIC_EXCEPTION import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.RUNTIME_DIAGNOSTIC_LOG import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot +import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* @@ -461,6 +462,7 @@ class K2JsIrCompiler : CLICompiler() { sourceModule.jsFrontEndResult.hasErrors ) + val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() generateKLib( sourceModule, outputKlibPath, @@ -468,10 +470,17 @@ class K2JsIrCompiler : CLICompiler() { jsOutputName = arguments.irPerModuleOutputName, icData = icData, moduleFragment = moduleFragment, + diagnosticReporter = diagnosticsReporter, builtInsPlatform = if (arguments.wasm) BuiltInsPlatform.WASM else BuiltInsPlatform.JS ) { file -> metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor) } + + val messageCollector = environmentForJS.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + reportCollectedDiagnostics(environmentForJS.configuration, diagnosticsReporter, messageCollector) + if (diagnosticsReporter.hasErrors) { + throw CompilationErrorException() + } } return sourceModule } @@ -556,6 +565,11 @@ class K2JsIrCompiler : CLICompiler() { jsOutputName = arguments.irPerModuleOutputName, useWasmPlatform = arguments.wasm ) + + reportCollectedDiagnostics(moduleStructure.compilerConfiguration, diagnosticsReporter, messageCollector) + if (diagnosticsReporter.hasErrors) { + throw CompilationErrorException() + } } return moduleStructure diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/klib/compilerPipeline.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/klib/compilerPipeline.kt index 3adabebbc08..33b45dd48d5 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/klib/compilerPipeline.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/klib/compilerPipeline.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.constant.EvaluatedConstTracker import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl @@ -116,6 +117,15 @@ inline fun compileModuleToAnalyzedFir( return outputs } +internal fun reportCollectedDiagnostics( + compilerConfiguration: CompilerConfiguration, + diagnosticsReporter: BaseDiagnosticsCollector, + messageCollector: MessageCollector +) { + val renderName = compilerConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) + FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderName) +} + open class AnalyzedFirOutput(val output: List) { protected open fun checkSyntaxErrors(messageCollector: MessageCollector) = false @@ -125,8 +135,7 @@ open class AnalyzedFirOutput(val output: List) { messageCollector: MessageCollector, ): Boolean { if (checkSyntaxErrors(messageCollector) || diagnosticsReporter.hasErrors) { - val renderName = moduleStructure.compilerConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) - FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderName) + reportCollectedDiagnostics(moduleStructure.compilerConfiguration, diagnosticsReporter, messageCollector) return true } @@ -318,6 +327,7 @@ fun serializeFirKlib( moduleStructure.compilerConfiguration[CommonConfigurationKeys.MODULE_NAME]!!, moduleStructure.compilerConfiguration, moduleStructure.compilerConfiguration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, + diagnosticsReporter, fir2KlibSerializer.sourceFiles, klibPath = outputKlibPath, moduleStructure.allDependencies, diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibCheckers.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibCheckers.kt new file mode 100644 index 00000000000..4419383021a --- /dev/null +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibCheckers.kt @@ -0,0 +1,37 @@ +/* + * 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.backend.js.checkers + +import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.ir.backend.js.checkers.declarations.JsKlibEsModuleExportsChecker +import org.jetbrains.kotlin.ir.backend.js.checkers.declarations.JsKlibOtherModuleExportsChecker +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.library.SerializedIrFile + +object JsKlibCheckers { + private val exportedDeclarationsCheckers = listOf( + JsKlibEsModuleExportsChecker, + JsKlibOtherModuleExportsChecker + ) + + fun check( + cleanFiles: List, + dirtyFiles: List, + exportedNames: Map>, + diagnosticReporter: DiagnosticReporter, + configuration: CompilerConfiguration + ) { + val reporter = KtDiagnosticReporterWithImplicitIrBasedContext(diagnosticReporter, configuration.languageVersionSettings) + val exportedDeclarations = JsKlibExportingDeclaration.collectDeclarations(cleanFiles, dirtyFiles, exportedNames) + for (checker in exportedDeclarationsCheckers) { + checker.check(exportedDeclarations, reporter) + } + } +} diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibDeclarationsChecker.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibDeclarationsChecker.kt new file mode 100644 index 00000000000..6eb6dff902d --- /dev/null +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibDeclarationsChecker.kt @@ -0,0 +1,14 @@ +/* + * 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.backend.js.checkers + +import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext + +interface JsKlibDeclarationsChecker { + fun check(declarations: List, reporter: KtDiagnosticReporterWithImplicitIrBasedContext) +} + +typealias JsKlibExportedDeclarationsChecker = JsKlibDeclarationsChecker diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibErrors.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibErrors.kt new file mode 100644 index 00000000000..db08243c547 --- /dev/null +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibErrors.kt @@ -0,0 +1,47 @@ +/* + * 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.backend.js.checkers + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap +import org.jetbrains.kotlin.diagnostics.error2 +import org.jetbrains.kotlin.diagnostics.rendering.* +import org.jetbrains.kotlin.diagnostics.warning2 + +object JsKlibErrors { + val EXPORTING_JS_NAME_CLASH by error2>() + val EXPORTING_JS_NAME_CLASH_ES by warning2>() + + init { + RootDiagnosticRendererFactory.registerFactory(KtDefaultJsKlibErrorMessages) + } +} + +private object KtDefaultJsKlibErrorMessages : BaseDiagnosticRendererFactory() { + @JvmField + val JS_KLIB_EXPORTS = Renderer> { exports -> + if (exports.size == 1) { + exports.single().render() + } else { + exports.sortedBy { it.containingFile }.joinToString("\n", "\n", limit = 10) { " ${it.render()}" } + } + } + + override val MAP = KtDiagnosticFactoryToRendererMap("KT").also { map -> + map.put( + JsKlibErrors.EXPORTING_JS_NAME_CLASH, + "Exporting name ''{0}'' clashes with {1}", + CommonRenderers.STRING, + JS_KLIB_EXPORTS + ) + map.put( + JsKlibErrors.EXPORTING_JS_NAME_CLASH_ES, + "Exporting name ''{0}'' in ES modules may clash with {1}", + CommonRenderers.STRING, + JS_KLIB_EXPORTS, + ) + } +} diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibExportingDeclaration.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibExportingDeclaration.kt new file mode 100644 index 00000000000..6cdf1c4fdcb --- /dev/null +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/JsKlibExportingDeclaration.kt @@ -0,0 +1,57 @@ +/* + * 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.backend.js.checkers + +import org.jetbrains.kotlin.ir.backend.js.fileMetadata +import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrFileMetadata +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.library.SerializedIrFile + +abstract class JsKlibExport(val containingFile: String) { + abstract val fqName: String + abstract fun render(): String +} + +class JsKlibExportingPackage(containingFile: String, override val fqName: String) : JsKlibExport(containingFile) { + override fun render() = "package '$fqName' from file '$containingFile'" +} + +class JsKlibExportingDeclaration( + val exportingName: String, + containingFile: String, + packageFqName: String, + val declaration: IrDeclaration?, +) : JsKlibExport(containingFile) { + constructor(name: String, file: SerializedIrFile) : this(name, file.path, file.fqName, null) + constructor(name: String, file: IrFile, decl: IrDeclaration) : this(name, file.fileEntry.name, file.packageFqName.toString(), decl) + + val containingPackageFqName = packageFqName.takeIf { it != "" } ?: "" + override val fqName = "$containingPackageFqName${".".takeIf { containingPackageFqName.isNotEmpty() } ?: ""}$exportingName" + override fun render() = "exporting name '$exportingName' from file '$containingFile'" + + companion object { + fun collectDeclarations( + cleanFiles: List, + dirtyFiles: List, + exportedNames: Map>, + ) = buildList { + for (serializedFile in cleanFiles) { + val fileMetadata = JsIrFileMetadata.fromByteArray(serializedFile.fileMetadata) + for (exportedName in fileMetadata.exportedNames) { + add(JsKlibExportingDeclaration(exportedName, serializedFile)) + } + } + for (dirtyFile in dirtyFiles) { + val exportedDeclarations = exportedNames[dirtyFile] ?: continue + for ((declaration, exportedName) in exportedDeclarations) { + add(JsKlibExportingDeclaration(exportedName, dirtyFile, declaration)) + } + } + } + } +} diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/declarations/JsKlibEsModuleExportsChecker.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/declarations/JsKlibEsModuleExportsChecker.kt new file mode 100644 index 00000000000..d039a1f7237 --- /dev/null +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/declarations/JsKlibEsModuleExportsChecker.kt @@ -0,0 +1,28 @@ +/* + * 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.backend.js.checkers.declarations + +import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext +import org.jetbrains.kotlin.ir.backend.js.checkers.JsKlibExportingDeclaration +import org.jetbrains.kotlin.ir.backend.js.checkers.JsKlibExportedDeclarationsChecker +import org.jetbrains.kotlin.ir.backend.js.checkers.JsKlibErrors + +object JsKlibEsModuleExportsChecker : JsKlibExportedDeclarationsChecker { + override fun check( + declarations: List, + reporter: KtDiagnosticReporterWithImplicitIrBasedContext, + ) { + val allExportedNameClashes = declarations.groupBy { it.exportingName }.filterValues { it.size > 1 } + + for (exportedDeclarationClashes in allExportedNameClashes.values) { + for ((index, exportedDeclaration) in exportedDeclarationClashes.withIndex()) { + val declaration = exportedDeclaration.declaration ?: continue + val clashedWith = exportedDeclarationClashes.filterIndexed { i, _ -> i != index } + reporter.at(declaration).report(JsKlibErrors.EXPORTING_JS_NAME_CLASH_ES, exportedDeclaration.exportingName, clashedWith) + } + } + } +} diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/declarations/JsKlibOtherModuleExportsChecker.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/declarations/JsKlibOtherModuleExportsChecker.kt new file mode 100644 index 00000000000..c1a9d5de670 --- /dev/null +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/checkers/declarations/JsKlibOtherModuleExportsChecker.kt @@ -0,0 +1,55 @@ +/* + * 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.backend.js.checkers.declarations + +import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext +import org.jetbrains.kotlin.ir.backend.js.checkers.* + +object JsKlibOtherModuleExportsChecker : JsKlibExportedDeclarationsChecker { + private fun MutableMap>.addExport(key: T, export: JsKlibExport) { + getOrPut(key) { mutableListOf() }.add(export) + } + + private fun collectClashesByFqNames(declarations: List): Map> { + return buildMap> { + for (declaration in declarations) { + addExport(declaration.fqName, declaration) + + var packageFqName = declaration.containingPackageFqName + while (packageFqName.isNotEmpty()) { + addExport(packageFqName, JsKlibExportingPackage(declaration.containingFile, packageFqName)) + + packageFqName = packageFqName.substringBeforeLast(".", "") + } + } + } + } + + private fun collectClashes(declarations: List): Map> { + val clashesByFqNames = collectClashesByFqNames(declarations) + return buildMap { + for (clashingExports in clashesByFqNames.values) { + for ((index, export) in clashingExports.withIndex()) { + if (export is JsKlibExportingDeclaration) { + val clashedWith = clashingExports.filterIndexed { i, _ -> i != index } + if (clashedWith.isNotEmpty()) { + put(export, clashedWith) + } + } + } + } + } + } + + override fun check(declarations: List, reporter: KtDiagnosticReporterWithImplicitIrBasedContext) { + val clashes = collectClashes(declarations) + for ((declaration, clashedWith) in clashes) { + if (declaration.declaration != null) { + reporter.at(declaration.declaration).report(JsKlibErrors.EXPORTING_JS_NAME_CLASH, declaration.exportingName, clashedWith) + } + } + } +} diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 7421ec82fbd..dcec50eb8c9 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -32,10 +32,12 @@ import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.backend.js.checkers.JsKlibCheckers import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.* import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrModuleFragment @@ -71,9 +73,9 @@ import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.util.DummyLogger import org.jetbrains.kotlin.util.Logger import org.jetbrains.kotlin.utils.DFS -import org.jetbrains.kotlin.utils.addToStdlib.flatGroupBy import org.jetbrains.kotlin.utils.addToStdlib.ifTrue import org.jetbrains.kotlin.utils.memoryOptimizedFilter +import org.jetbrains.kotlin.utils.toSmartList import java.io.File val KotlinLibrary.moduleName: String @@ -98,7 +100,7 @@ val KotlinLibrary.serializedKlibFingerprint: SerializedKlibFingerprint? private val CompilerConfiguration.metadataVersion get() = get(CommonConfigurationKeys.METADATA_VERSION) as? KlibMetadataVersion ?: KlibMetadataVersion.INSTANCE -private val SerializedIrFile.fileMetadata: ByteArray +internal val SerializedIrFile.fileMetadata: ByteArray get() = backendSpecificMetadata ?: error("Expect file caches to have backendSpecificMetadata, but '$path' doesn't") val CompilerConfiguration.resolverLogger: Logger @@ -126,6 +128,7 @@ fun generateKLib( jsOutputName: String?, icData: List, moduleFragment: IrModuleFragment, + diagnosticReporter: DiagnosticReporter, builtInsPlatform: BuiltInsPlatform = BuiltInsPlatform.JS, serializeSingleFile: (KtSourceFile) -> ProtoBuf.PackageFragment ) { @@ -138,6 +141,7 @@ fun generateKLib( configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration, messageLogger, + diagnosticReporter, files, outputKlibPath, allDependencies, @@ -623,33 +627,11 @@ private fun String.parseSerializedIrFileFingerprints(): List) { - val allExportedNameClashes = files - .flatGroupBy { JsIrFileMetadata.fromByteArray(it.irData.fileMetadata).exportedNames } - .filterValues { it.size > 1 } - - if (allExportedNameClashes.isEmpty()) return - - val nameClashesString = buildString { - allExportedNameClashes.forEach { (name, files) -> - appendLine(" * Next files contain declarations with @JsExport and name '$name'") - files.forEach { appendLine(" - ${it.irData.path}") } - } - } - - val message = """ - |There are clashes of declaration names that annotated with @JsExport in module '$moduleName'. - |${nameClashesString} - |Note, that this clash could affect the generated JS code in case of ES module kind usage - """.trimMargin() - - irMessageLogger.report(IrMessageLogger.Severity.WARNING, message, null) -} - fun serializeModuleIntoKlib( moduleName: String, configuration: CompilerConfiguration, messageLogger: IrMessageLogger, + diagnosticReporter: DiagnosticReporter, files: List, klibPath: String, dependencies: List, @@ -670,6 +652,13 @@ fun serializeModuleIntoKlib( val absolutePathNormalization = configuration[CommonConfigurationKeys.KLIB_NORMALIZE_ABSOLUTE_PATH] ?: false val signatureClashChecks = configuration[CommonConfigurationKeys.PRODUCE_KLIB_SIGNATURES_CLASH_CHECKS] ?: false + val moduleExportedNames = moduleFragment.collectExportedNames() + + if (builtInsPlatform == BuiltInsPlatform.JS) { + val cleanFilesIrData = cleanFiles.map { it.irData } + JsKlibCheckers.check(cleanFilesIrData, moduleFragment.files, moduleExportedNames, diagnosticReporter, configuration) + } + val serializedIr = JsIrModuleSerializer( messageLogger, @@ -678,7 +667,8 @@ fun serializeModuleIntoKlib( normalizeAbsolutePaths = absolutePathNormalization, sourceBaseDirs = sourceBaseDirs, configuration.languageVersionSettings, - signatureClashChecks + signatureClashChecks, + jsIrFileMetadataFactory = { JsIrFileMetadata(moduleExportedNames[it]?.values?.toSmartList() ?: emptyList()) } ).serializedIrModule(moduleFragment) val moduleDescriptor = moduleFragment.descriptor @@ -726,11 +716,7 @@ fun serializeModuleIntoKlib( processCompiledFileData(ioFile!!, compiledKotlinFile) } - val compiledKotlinFiles = (cleanFiles + additionalFiles).also { - if (builtInsPlatform == BuiltInsPlatform.JS) { - configuration.assertNoExportedNamesClashes(moduleName, it) - } - } + val compiledKotlinFiles = cleanFiles + additionalFiles val header = serializeKlibHeader( configuration.languageVersionSettings, moduleDescriptor, diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsExportUtils.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsExportUtils.kt new file mode 100644 index 00000000000..77f1cfba575 --- /dev/null +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsExportUtils.kt @@ -0,0 +1,48 @@ +/* + * 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.backend.js.lower.serialization.ir + +import org.jetbrains.kotlin.backend.common.ir.isExpect +import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.expressions.IrConst +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.util.getAnnotation +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.ir.util.isEffectivelyExternal +import org.jetbrains.kotlin.name.JsStandardClassIds + +internal fun IrAnnotationContainer.isExportedDeclaration(): Boolean { + return annotations.hasAnnotation(JsStandardClassIds.Annotations.JsExport.asSingleFqName()) && !isExportIgnoreDeclaration() +} + +internal fun IrAnnotationContainer.isExportIgnoreDeclaration(): Boolean { + return annotations.hasAnnotation(JsStandardClassIds.Annotations.JsExportIgnore.asSingleFqName()) +} + +private val IrDeclarationWithName.exportedName: String + get() = getAnnotation(JsStandardClassIds.Annotations.JsName.asSingleFqName())?.getSingleConstStringArgument() ?: name.toString() + +@Suppress("UNCHECKED_CAST") +private fun IrConstructorCall.getSingleConstStringArgument() = + (getValueArgument(0) as IrConst).value + +fun IrModuleFragment.collectExportedNames(): Map> { + return files.associateWith { irFile -> + val isFileExported = irFile.annotations.hasAnnotation(JsStandardClassIds.Annotations.JsExport.asSingleFqName()) + + val exportedDeclarations = irFile.declarations.asSequence() + .filterIsInstance() + .filter { if (isFileExported) !it.isExportIgnoreDeclaration() else it.isExportedDeclaration() } + .filter { !it.isEffectivelyExternal() && !it.isExpect } + .map { + it to it.exportedName + }.toMap() + exportedDeclarations + } +} diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrFileMetadata.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrFileMetadata.kt index 627ebd4bda6..7c2a3357763 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrFileMetadata.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrFileMetadata.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer import org.jetbrains.kotlin.library.impl.toArray import org.jetbrains.kotlin.library.encodings.WobblyTF8 -import org.jetbrains.kotlin.library.impl.IrMemoryArrayWriter import org.jetbrains.kotlin.library.impl.IrMemoryStringWriter import org.jetbrains.kotlin.library.impl.IrArrayMemoryReader @@ -24,4 +23,4 @@ class JsIrFileMetadata(val exportedNames: List) : IrFileSerializer.FileB ) } } -} \ No newline at end of file +} diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrFileSerializer.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrFileSerializer.kt index 5d3accc7632..5698e77cab7 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrFileSerializer.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrFileSerializer.kt @@ -5,21 +5,21 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir -import org.jetbrains.kotlin.backend.common.ir.isExpect import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer -import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.expressions.IrConst -import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.util.IrMessageLogger -import org.jetbrains.kotlin.ir.util.getAnnotation -import org.jetbrains.kotlin.ir.util.hasAnnotation -import org.jetbrains.kotlin.ir.util.isEffectivelyExternal -import org.jetbrains.kotlin.name.FqName + +fun interface JsIrFileMetadataFactory { + fun createJsIrFileMetadata(irFile: IrFile): JsIrFileMetadata +} + +object JsIrFileEmptyMetadataFactory : JsIrFileMetadataFactory { + override fun createJsIrFileMetadata(irFile: IrFile) = JsIrFileMetadata(emptyList()) +} class JsIrFileSerializer( messageLogger: IrMessageLogger, @@ -28,7 +28,8 @@ class JsIrFileSerializer( languageVersionSettings: LanguageVersionSettings, bodiesOnlyForInlines: Boolean = false, normalizeAbsolutePaths: Boolean, - sourceBaseDirs: Collection + sourceBaseDirs: Collection, + private val jsIrFileMetadataFactory: JsIrFileMetadataFactory ) : IrFileSerializer( messageLogger, declarationTable, @@ -38,39 +39,7 @@ class JsIrFileSerializer( normalizeAbsolutePaths = normalizeAbsolutePaths, sourceBaseDirs = sourceBaseDirs ) { - companion object { - private val JS_NAME_FQN = FqName("kotlin.js.JsName") - private val JS_EXPORT_FQN = FqName("kotlin.js.JsExport") - private val JS_EXPORT_IGNORE_FQN = FqName("kotlin.js.JsExport.Ignore") - } - - private fun IrAnnotationContainer.isExportedDeclaration(): Boolean { - return annotations.hasAnnotation(JS_EXPORT_FQN) && !isExportIgnoreDeclaration() - } - - private fun IrAnnotationContainer.isExportIgnoreDeclaration(): Boolean { - return annotations.hasAnnotation(JS_EXPORT_IGNORE_FQN) - } - - private val IrDeclarationWithName.exportedName: String - get() = getAnnotation(JS_NAME_FQN)?.getSingleConstStringArgument() ?: name.toString() - override fun backendSpecificExplicitRoot(node: IrAnnotationContainer) = node.isExportedDeclaration() override fun backendSpecificExplicitRootExclusion(node: IrAnnotationContainer) = node.isExportIgnoreDeclaration() - override fun backendSpecificMetadata(irFile: IrFile): FileBackendSpecificMetadata { - val isFileExported = irFile.annotations.hasAnnotation(JS_EXPORT_FQN) - - val exportedNames = irFile.declarations.asSequence() - .filterIsInstance() - .filter { if (isFileExported) !it.isExportIgnoreDeclaration() else it.isExportedDeclaration() } - .filter { !it.isEffectivelyExternal() && !it.isExpect } - .map { it.exportedName } - .toList() - - return JsIrFileMetadata(exportedNames) - } - - @Suppress("UNCHECKED_CAST") - private fun IrConstructorCall.getSingleConstStringArgument() = - (getValueArgument(0) as IrConst).value + override fun backendSpecificMetadata(irFile: IrFile) = jsIrFileMetadataFactory.createJsIrFileMetadata(irFile) } diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrModuleSerializer.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrModuleSerializer.kt index a00d101529d..cea831f7e9c 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrModuleSerializer.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrModuleSerializer.kt @@ -21,7 +21,8 @@ class JsIrModuleSerializer( normalizeAbsolutePaths: Boolean, sourceBaseDirs: Collection, private val languageVersionSettings: LanguageVersionSettings, - shouldCheckSignaturesOnUniqueness: Boolean = true + shouldCheckSignaturesOnUniqueness: Boolean = true, + private val jsIrFileMetadataFactory: JsIrFileMetadataFactory = JsIrFileEmptyMetadataFactory ) : IrModuleSerializer(messageLogger, compatibilityMode, normalizeAbsolutePaths, sourceBaseDirs) { private val globalDeclarationTable = JsGlobalDeclarationTable( @@ -37,5 +38,6 @@ class JsIrModuleSerializer( normalizeAbsolutePaths = normalizeAbsolutePaths, sourceBaseDirs = sourceBaseDirs, languageVersionSettings = languageVersionSettings, + jsIrFileMetadataFactory = jsIrFileMetadataFactory ) -} \ No newline at end of file +} diff --git a/compiler/testData/multiplatform/jsNameClash/output.txt b/compiler/testData/multiplatform/jsNameClash/output.txt index 6b3f5dfc27f..ce51cebf799 100644 --- a/compiler/testData/multiplatform/jsNameClash/output.txt +++ b/compiler/testData/multiplatform/jsNameClash/output.txt @@ -5,3 +5,9 @@ Output: -- JS -- Exit code: OK Output: +compiler/testData/multiplatform/jsNameClash/common.kt:1:1: warning: 'expect'/'actual' classes (including interfaces, objects, annotations, enums, and 'actual' typealiases) are in Beta. You can use -Xexpect-actual-classes flag to suppress this warning. Also see: https://youtrack.jetbrains.com/issue/KT-61573 +expect class ClassWithImplByExtension +^ +compiler/testData/multiplatform/jsNameClash/js.kt:1:1: warning: 'expect'/'actual' classes (including interfaces, objects, annotations, enums, and 'actual' typealiases) are in Beta. You can use -Xexpect-actual-classes flag to suppress this warning. Also see: https://youtrack.jetbrains.com/issue/KT-61573 +actual class ClassWithImplByExtension +^ diff --git a/compiler/testData/multiplatform/optionalExpectation/output.txt b/compiler/testData/multiplatform/optionalExpectation/output.txt index bd464eefcb7..f62dc37910f 100644 --- a/compiler/testData/multiplatform/optionalExpectation/output.txt +++ b/compiler/testData/multiplatform/optionalExpectation/output.txt @@ -15,3 +15,6 @@ actual annotation class A -- JS -- Exit code: OK Output: +compiler/testData/multiplatform/optionalExpectation/common.kt:5:1: warning: 'expect'/'actual' classes (including interfaces, objects, annotations, enums, and 'actual' typealiases) are in Beta. You can use -Xexpect-actual-classes flag to suppress this warning. Also see: https://youtrack.jetbrains.com/issue/KT-61573 +expect annotation class A() +^ diff --git a/compiler/testData/multiplatform/simple/output.txt b/compiler/testData/multiplatform/simple/output.txt index f325abcdea3..1c536a19351 100644 --- a/compiler/testData/multiplatform/simple/output.txt +++ b/compiler/testData/multiplatform/simple/output.txt @@ -15,3 +15,9 @@ actual class Printer { -- JS -- Exit code: OK Output: +compiler/testData/multiplatform/simple/common.kt:1:1: warning: 'expect'/'actual' classes (including interfaces, objects, annotations, enums, and 'actual' typealiases) are in Beta. You can use -Xexpect-actual-classes flag to suppress this warning. Also see: https://youtrack.jetbrains.com/issue/KT-61573 +expect class Printer() { +^ +compiler/testData/multiplatform/simple/js.kt:1:1: warning: 'expect'/'actual' classes (including interfaces, objects, annotations, enums, and 'actual' typealiases) are in Beta. You can use -Xexpect-actual-classes flag to suppress this warning. Also see: https://youtrack.jetbrains.com/issue/KT-61573 +actual class Printer { +^ diff --git a/compiler/tests/org/jetbrains/kotlin/klib/FilePathsInKlibTest.kt b/compiler/tests/org/jetbrains/kotlin/klib/FilePathsInKlibTest.kt index cb78652a482..08ae9c69a00 100644 --- a/compiler/tests/org/jetbrains/kotlin/klib/FilePathsInKlibTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/klib/FilePathsInKlibTest.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.codegen.CodegenTestCase import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.incremental.md5 import org.jetbrains.kotlin.ir.backend.js.* import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl @@ -76,13 +77,15 @@ class FilePathsInKlibTest : CodegenTestCase() { val metadataSerializer = KlibMetadataIncrementalSerializer(module.compilerConfiguration, module.project, module.jsFrontEndResult.hasErrors) + val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter() generateKLib( module, outputKlibPath = destination.path, nopack = false, jsOutputName = MODULE_NAME, icData = icData, - moduleFragment = moduleFragment + moduleFragment = moduleFragment, + diagnosticReporter = diagnosticReporter ) { file -> metadataSerializer.serializeScope(file, module.jsFrontEndResult.bindingContext, moduleFragment.descriptor) } diff --git a/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt b/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt index e624b45a166..db8bf0c73f4 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory @@ -36,6 +37,7 @@ import org.jetbrains.kotlin.ir.backend.js.* 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.backend.js.lower.serialization.ir.collectExportedNames import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode import org.jetbrains.kotlin.ir.declarations.IrModuleFragment @@ -490,12 +492,14 @@ class GenerateIrRuntime { files: List, perFile: Boolean = false ): String { + val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter() val tmpKlibDir = createTempDirectory().also { it.toFile().deleteOnExit() }.toString() val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, project, false) serializeModuleIntoKlib( moduleName, configuration, IrMessageLogger.None, + diagnosticReporter, files.map(::KtPsiSourceFile), tmpKlibDir, emptyList(), diff --git a/js/js.tests/test/org/jetbrains/kotlin/incremental/IrAbstractInvalidationTest.kt b/js/js.tests/test/org/jetbrains/kotlin/incremental/IrAbstractInvalidationTest.kt index 0ee77bbaad4..0a865baec81 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/incremental/IrAbstractInvalidationTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/incremental/IrAbstractInvalidationTest.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.incremental import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.js.klib.generateIrForKlibSerialization import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.ir.backend.js.* import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsGenerationGranularity import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl @@ -108,13 +109,15 @@ abstract class IrAbstractInvalidationTest( val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, sourceModule.project, sourceModule.jsFrontEndResult.hasErrors) + val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter() generateKLib( sourceModule, outputKlibFile.canonicalPath, nopack = false, jsOutputName = moduleName, icData = icData, - moduleFragment = moduleFragment + moduleFragment = moduleFragment, + diagnosticReporter = diagnosticReporter ) { file -> metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor) } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/FirJsKlibBackendFacade.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/FirJsKlibBackendFacade.kt index 8e7db279079..2a3cb3668bd 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/FirJsKlibBackendFacade.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/FirJsKlibBackendFacade.kt @@ -62,6 +62,7 @@ class FirJsKlibBackendFacade( configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration, configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, + inputArtifact.diagnosticReporter, inputArtifact.sourceFiles, klibPath = outputFile, libraries.map { it.library }, diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/JsKlibBackendFacade.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/JsKlibBackendFacade.kt index 5e0ed98b634..fbeecbbd9ad 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/JsKlibBackendFacade.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/JsKlibBackendFacade.kt @@ -51,6 +51,7 @@ class JsKlibBackendFacade( configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration, configuration.irMessageLogger, + inputArtifact.diagnosticReporter, inputArtifact.sourceFiles, klibPath = outputFile, JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices).keys.toList(), diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/AbstractJsPartialLinkageTestCase.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/AbstractJsPartialLinkageTestCase.kt index 9137a0792a3..9d2c6a11f63 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/AbstractJsPartialLinkageTestCase.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/AbstractJsPartialLinkageTestCase.kt @@ -112,12 +112,19 @@ abstract class AbstractJsPartialLinkageTestCase(private val compilerType: Compil "-Xir-produce-klib-file", "-ir-output-dir", klibFile.parentFile.absolutePath, "-ir-output-name", moduleName, - "-Werror" // Halt on any unexpected warning. + // Halt on any unexpected warning. + "-Werror", + // Tests suppress the INVISIBLE_REFERENCE check. + // However, JS doesn't produce the INVISIBLE_REFERENCE error; + // As result, it triggers a suppression error warning about the redundant suppression. + // This flag is used to disable the warning. + "-Xdont-warn-on-error-suppression" ), dependencies.toCompilerArgs(), listOf( "-language-version", "2.0", - "-Xsuppress-version-warnings" // Don't fail on language version warnings. + // Don't fail on language version warnings. + "-Xsuppress-version-warnings" ).takeIf { compilerType.useFir }, kotlinSourceFilePaths ) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt index 3bfc778101c..f0c30de5fd7 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt @@ -364,10 +364,7 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() { fun testProjectWithExportedNamesClash(gradleVersion: GradleVersion) { project("kotlin-js-invalid-project-with-exported-clash", gradleVersion) { build("compileKotlinJs") { - assertOutputContains(""" - |There are clashes of declaration names that annotated with @JsExport in module 'kotlin-js-invalid-project-with-exported-clash'. - | * Next files contain declarations with @JsExport and name 'best' - """.trimMargin()) + assertOutputContains("Exporting name 'best' in ES modules may clash") } } } diff --git a/wasm/wasm.tests/test/org/jetbrains/kotlin/wasm/test/converters/FirWasmKlibBackendFacade.kt b/wasm/wasm.tests/test/org/jetbrains/kotlin/wasm/test/converters/FirWasmKlibBackendFacade.kt index 5a9cf9351ce..d7927b2b7a9 100644 --- a/wasm/wasm.tests/test/org/jetbrains/kotlin/wasm/test/converters/FirWasmKlibBackendFacade.kt +++ b/wasm/wasm.tests/test/org/jetbrains/kotlin/wasm/test/converters/FirWasmKlibBackendFacade.kt @@ -62,6 +62,7 @@ class FirWasmKlibBackendFacade( configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration, configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, + inputArtifact.diagnosticReporter, inputArtifact.sourceFiles, klibPath = outputFile, libraries.map { it.library },