[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
This commit is contained in:
Alexander Korepanov
2023-09-07 22:08:22 +02:00
parent 13bd627bfa
commit 522952db1f
24 changed files with 385 additions and 87 deletions
@@ -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_EXCEPTION
import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.RUNTIME_DIAGNOSTIC_LOG 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.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.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
@@ -461,6 +462,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
sourceModule.jsFrontEndResult.hasErrors sourceModule.jsFrontEndResult.hasErrors
) )
val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
generateKLib( generateKLib(
sourceModule, sourceModule,
outputKlibPath, outputKlibPath,
@@ -468,10 +470,17 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
jsOutputName = arguments.irPerModuleOutputName, jsOutputName = arguments.irPerModuleOutputName,
icData = icData, icData = icData,
moduleFragment = moduleFragment, moduleFragment = moduleFragment,
diagnosticReporter = diagnosticsReporter,
builtInsPlatform = if (arguments.wasm) BuiltInsPlatform.WASM else BuiltInsPlatform.JS builtInsPlatform = if (arguments.wasm) BuiltInsPlatform.WASM else BuiltInsPlatform.JS
) { file -> ) { file ->
metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor) 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 return sourceModule
} }
@@ -556,6 +565,11 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
jsOutputName = arguments.irPerModuleOutputName, jsOutputName = arguments.irPerModuleOutputName,
useWasmPlatform = arguments.wasm useWasmPlatform = arguments.wasm
) )
reportCollectedDiagnostics(moduleStructure.compilerConfiguration, diagnosticsReporter, messageCollector)
if (diagnosticsReporter.hasErrors) {
throw CompilationErrorException()
}
} }
return moduleStructure return moduleStructure
@@ -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.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.constant.EvaluatedConstTracker import org.jetbrains.kotlin.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
@@ -116,6 +117,15 @@ inline fun <F> compileModuleToAnalyzedFir(
return outputs 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<ModuleCompilerAnalyzedOutput>) { open class AnalyzedFirOutput(val output: List<ModuleCompilerAnalyzedOutput>) {
protected open fun checkSyntaxErrors(messageCollector: MessageCollector) = false protected open fun checkSyntaxErrors(messageCollector: MessageCollector) = false
@@ -125,8 +135,7 @@ open class AnalyzedFirOutput(val output: List<ModuleCompilerAnalyzedOutput>) {
messageCollector: MessageCollector, messageCollector: MessageCollector,
): Boolean { ): Boolean {
if (checkSyntaxErrors(messageCollector) || diagnosticsReporter.hasErrors) { if (checkSyntaxErrors(messageCollector) || diagnosticsReporter.hasErrors) {
val renderName = moduleStructure.compilerConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) reportCollectedDiagnostics(moduleStructure.compilerConfiguration, diagnosticsReporter, messageCollector)
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderName)
return true return true
} }
@@ -318,6 +327,7 @@ fun serializeFirKlib(
moduleStructure.compilerConfiguration[CommonConfigurationKeys.MODULE_NAME]!!, moduleStructure.compilerConfiguration[CommonConfigurationKeys.MODULE_NAME]!!,
moduleStructure.compilerConfiguration, moduleStructure.compilerConfiguration,
moduleStructure.compilerConfiguration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, moduleStructure.compilerConfiguration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None,
diagnosticsReporter,
fir2KlibSerializer.sourceFiles, fir2KlibSerializer.sourceFiles,
klibPath = outputKlibPath, klibPath = outputKlibPath,
moduleStructure.allDependencies, moduleStructure.allDependencies,
@@ -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<SerializedIrFile>,
dirtyFiles: List<IrFile>,
exportedNames: Map<IrFile, Map<IrDeclarationWithName, String>>,
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)
}
}
}
@@ -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<D> {
fun check(declarations: List<D>, reporter: KtDiagnosticReporterWithImplicitIrBasedContext)
}
typealias JsKlibExportedDeclarationsChecker = JsKlibDeclarationsChecker<JsKlibExportingDeclaration>
@@ -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<PsiElement, String, List<JsKlibExport>>()
val EXPORTING_JS_NAME_CLASH_ES by warning2<PsiElement, String, List<JsKlibExport>>()
init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultJsKlibErrorMessages)
}
}
private object KtDefaultJsKlibErrorMessages : BaseDiagnosticRendererFactory() {
@JvmField
val JS_KLIB_EXPORTS = Renderer<List<JsKlibExport>> { 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,
)
}
}
@@ -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 != "<root>" } ?: ""
override val fqName = "$containingPackageFqName${".".takeIf { containingPackageFqName.isNotEmpty() } ?: ""}$exportingName"
override fun render() = "exporting name '$exportingName' from file '$containingFile'"
companion object {
fun collectDeclarations(
cleanFiles: List<SerializedIrFile>,
dirtyFiles: List<IrFile>,
exportedNames: Map<IrFile, Map<IrDeclarationWithName, String>>,
) = 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))
}
}
}
}
}
@@ -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<JsKlibExportingDeclaration>,
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)
}
}
}
}
@@ -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 <T> MutableMap<T, MutableList<JsKlibExport>>.addExport(key: T, export: JsKlibExport) {
getOrPut(key) { mutableListOf() }.add(export)
}
private fun collectClashesByFqNames(declarations: List<JsKlibExportingDeclaration>): Map<String, List<JsKlibExport>> {
return buildMap<String, MutableList<JsKlibExport>> {
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<JsKlibExportingDeclaration>): Map<JsKlibExportingDeclaration, List<JsKlibExport>> {
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<JsKlibExportingDeclaration>, 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)
}
}
}
}
@@ -32,10 +32,12 @@ import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl 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.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI 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.backend.js.lower.serialization.ir.*
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment 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.DummyLogger
import org.jetbrains.kotlin.util.Logger import org.jetbrains.kotlin.util.Logger
import org.jetbrains.kotlin.utils.DFS 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.addToStdlib.ifTrue
import org.jetbrains.kotlin.utils.memoryOptimizedFilter import org.jetbrains.kotlin.utils.memoryOptimizedFilter
import org.jetbrains.kotlin.utils.toSmartList
import java.io.File import java.io.File
val KotlinLibrary.moduleName: String val KotlinLibrary.moduleName: String
@@ -98,7 +100,7 @@ val KotlinLibrary.serializedKlibFingerprint: SerializedKlibFingerprint?
private val CompilerConfiguration.metadataVersion private val CompilerConfiguration.metadataVersion
get() = get(CommonConfigurationKeys.METADATA_VERSION) as? KlibMetadataVersion ?: KlibMetadataVersion.INSTANCE 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") get() = backendSpecificMetadata ?: error("Expect file caches to have backendSpecificMetadata, but '$path' doesn't")
val CompilerConfiguration.resolverLogger: Logger val CompilerConfiguration.resolverLogger: Logger
@@ -126,6 +128,7 @@ fun generateKLib(
jsOutputName: String?, jsOutputName: String?,
icData: List<KotlinFileSerializedData>, icData: List<KotlinFileSerializedData>,
moduleFragment: IrModuleFragment, moduleFragment: IrModuleFragment,
diagnosticReporter: DiagnosticReporter,
builtInsPlatform: BuiltInsPlatform = BuiltInsPlatform.JS, builtInsPlatform: BuiltInsPlatform = BuiltInsPlatform.JS,
serializeSingleFile: (KtSourceFile) -> ProtoBuf.PackageFragment serializeSingleFile: (KtSourceFile) -> ProtoBuf.PackageFragment
) { ) {
@@ -138,6 +141,7 @@ fun generateKLib(
configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration, configuration,
messageLogger, messageLogger,
diagnosticReporter,
files, files,
outputKlibPath, outputKlibPath,
allDependencies, allDependencies,
@@ -623,33 +627,11 @@ private fun String.parseSerializedIrFileFingerprints(): List<SerializedIrFileFin
return split(FILE_FINGERPRINTS_SEPARATOR).mapNotNull(SerializedIrFileFingerprint::fromString) return split(FILE_FINGERPRINTS_SEPARATOR).mapNotNull(SerializedIrFileFingerprint::fromString)
} }
private fun CompilerConfiguration.assertNoExportedNamesClashes(moduleName: String, files: List<KotlinFileSerializedData>) {
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( fun serializeModuleIntoKlib(
moduleName: String, moduleName: String,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
messageLogger: IrMessageLogger, messageLogger: IrMessageLogger,
diagnosticReporter: DiagnosticReporter,
files: List<KtSourceFile>, files: List<KtSourceFile>,
klibPath: String, klibPath: String,
dependencies: List<KotlinLibrary>, dependencies: List<KotlinLibrary>,
@@ -670,6 +652,13 @@ fun serializeModuleIntoKlib(
val absolutePathNormalization = configuration[CommonConfigurationKeys.KLIB_NORMALIZE_ABSOLUTE_PATH] ?: false val absolutePathNormalization = configuration[CommonConfigurationKeys.KLIB_NORMALIZE_ABSOLUTE_PATH] ?: false
val signatureClashChecks = configuration[CommonConfigurationKeys.PRODUCE_KLIB_SIGNATURES_CLASH_CHECKS] ?: 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 = val serializedIr =
JsIrModuleSerializer( JsIrModuleSerializer(
messageLogger, messageLogger,
@@ -678,7 +667,8 @@ fun serializeModuleIntoKlib(
normalizeAbsolutePaths = absolutePathNormalization, normalizeAbsolutePaths = absolutePathNormalization,
sourceBaseDirs = sourceBaseDirs, sourceBaseDirs = sourceBaseDirs,
configuration.languageVersionSettings, configuration.languageVersionSettings,
signatureClashChecks signatureClashChecks,
jsIrFileMetadataFactory = { JsIrFileMetadata(moduleExportedNames[it]?.values?.toSmartList() ?: emptyList()) }
).serializedIrModule(moduleFragment) ).serializedIrModule(moduleFragment)
val moduleDescriptor = moduleFragment.descriptor val moduleDescriptor = moduleFragment.descriptor
@@ -726,11 +716,7 @@ fun serializeModuleIntoKlib(
processCompiledFileData(ioFile!!, compiledKotlinFile) processCompiledFileData(ioFile!!, compiledKotlinFile)
} }
val compiledKotlinFiles = (cleanFiles + additionalFiles).also { val compiledKotlinFiles = cleanFiles + additionalFiles
if (builtInsPlatform == BuiltInsPlatform.JS) {
configuration.assertNoExportedNamesClashes(moduleName, it)
}
}
val header = serializeKlibHeader( val header = serializeKlibHeader(
configuration.languageVersionSettings, moduleDescriptor, configuration.languageVersionSettings, moduleDescriptor,
@@ -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<String>).value
fun IrModuleFragment.collectExportedNames(): Map<IrFile, Map<IrDeclarationWithName, String>> {
return files.associateWith { irFile ->
val isFileExported = irFile.annotations.hasAnnotation(JsStandardClassIds.Annotations.JsExport.asSingleFqName())
val exportedDeclarations = irFile.declarations.asSequence()
.filterIsInstance<IrDeclarationWithName>()
.filter { if (isFileExported) !it.isExportIgnoreDeclaration() else it.isExportedDeclaration() }
.filter { !it.isEffectivelyExternal() && !it.isExpect }
.map {
it to it.exportedName
}.toMap()
exportedDeclarations
}
}
@@ -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.backend.common.serialization.IrFileSerializer
import org.jetbrains.kotlin.library.impl.toArray import org.jetbrains.kotlin.library.impl.toArray
import org.jetbrains.kotlin.library.encodings.WobblyTF8 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.IrMemoryStringWriter
import org.jetbrains.kotlin.library.impl.IrArrayMemoryReader import org.jetbrains.kotlin.library.impl.IrArrayMemoryReader
@@ -5,21 +5,21 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir 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.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer 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.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.IrMessageLogger
import org.jetbrains.kotlin.ir.util.getAnnotation
import org.jetbrains.kotlin.ir.util.hasAnnotation fun interface JsIrFileMetadataFactory {
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal fun createJsIrFileMetadata(irFile: IrFile): JsIrFileMetadata
import org.jetbrains.kotlin.name.FqName }
object JsIrFileEmptyMetadataFactory : JsIrFileMetadataFactory {
override fun createJsIrFileMetadata(irFile: IrFile) = JsIrFileMetadata(emptyList())
}
class JsIrFileSerializer( class JsIrFileSerializer(
messageLogger: IrMessageLogger, messageLogger: IrMessageLogger,
@@ -28,7 +28,8 @@ class JsIrFileSerializer(
languageVersionSettings: LanguageVersionSettings, languageVersionSettings: LanguageVersionSettings,
bodiesOnlyForInlines: Boolean = false, bodiesOnlyForInlines: Boolean = false,
normalizeAbsolutePaths: Boolean, normalizeAbsolutePaths: Boolean,
sourceBaseDirs: Collection<String> sourceBaseDirs: Collection<String>,
private val jsIrFileMetadataFactory: JsIrFileMetadataFactory
) : IrFileSerializer( ) : IrFileSerializer(
messageLogger, messageLogger,
declarationTable, declarationTable,
@@ -38,39 +39,7 @@ class JsIrFileSerializer(
normalizeAbsolutePaths = normalizeAbsolutePaths, normalizeAbsolutePaths = normalizeAbsolutePaths,
sourceBaseDirs = sourceBaseDirs 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 backendSpecificExplicitRoot(node: IrAnnotationContainer) = node.isExportedDeclaration()
override fun backendSpecificExplicitRootExclusion(node: IrAnnotationContainer) = node.isExportIgnoreDeclaration() override fun backendSpecificExplicitRootExclusion(node: IrAnnotationContainer) = node.isExportIgnoreDeclaration()
override fun backendSpecificMetadata(irFile: IrFile): FileBackendSpecificMetadata { override fun backendSpecificMetadata(irFile: IrFile) = jsIrFileMetadataFactory.createJsIrFileMetadata(irFile)
val isFileExported = irFile.annotations.hasAnnotation(JS_EXPORT_FQN)
val exportedNames = irFile.declarations.asSequence()
.filterIsInstance<IrDeclarationWithName>()
.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<String>).value
} }
@@ -21,7 +21,8 @@ class JsIrModuleSerializer(
normalizeAbsolutePaths: Boolean, normalizeAbsolutePaths: Boolean,
sourceBaseDirs: Collection<String>, sourceBaseDirs: Collection<String>,
private val languageVersionSettings: LanguageVersionSettings, private val languageVersionSettings: LanguageVersionSettings,
shouldCheckSignaturesOnUniqueness: Boolean = true shouldCheckSignaturesOnUniqueness: Boolean = true,
private val jsIrFileMetadataFactory: JsIrFileMetadataFactory = JsIrFileEmptyMetadataFactory
) : IrModuleSerializer<JsIrFileSerializer>(messageLogger, compatibilityMode, normalizeAbsolutePaths, sourceBaseDirs) { ) : IrModuleSerializer<JsIrFileSerializer>(messageLogger, compatibilityMode, normalizeAbsolutePaths, sourceBaseDirs) {
private val globalDeclarationTable = JsGlobalDeclarationTable( private val globalDeclarationTable = JsGlobalDeclarationTable(
@@ -37,5 +38,6 @@ class JsIrModuleSerializer(
normalizeAbsolutePaths = normalizeAbsolutePaths, normalizeAbsolutePaths = normalizeAbsolutePaths,
sourceBaseDirs = sourceBaseDirs, sourceBaseDirs = sourceBaseDirs,
languageVersionSettings = languageVersionSettings, languageVersionSettings = languageVersionSettings,
jsIrFileMetadataFactory = jsIrFileMetadataFactory
) )
} }
@@ -5,3 +5,9 @@ Output:
-- JS -- -- JS --
Exit code: OK Exit code: OK
Output: 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
^
@@ -15,3 +15,6 @@ actual annotation class A
-- JS -- -- JS --
Exit code: OK Exit code: OK
Output: 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()
^
+6
View File
@@ -15,3 +15,9 @@ actual class Printer {
-- JS -- -- JS --
Exit code: OK Exit code: OK
Output: 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 {
^
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.CodegenTestCase import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.incremental.md5 import org.jetbrains.kotlin.incremental.md5
import org.jetbrains.kotlin.ir.backend.js.* import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
@@ -76,13 +77,15 @@ class FilePathsInKlibTest : CodegenTestCase() {
val metadataSerializer = val metadataSerializer =
KlibMetadataIncrementalSerializer(module.compilerConfiguration, module.project, module.jsFrontEndResult.hasErrors) KlibMetadataIncrementalSerializer(module.compilerConfiguration, module.project, module.jsFrontEndResult.hasErrors)
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
generateKLib( generateKLib(
module, module,
outputKlibPath = destination.path, outputKlibPath = destination.path,
nopack = false, nopack = false,
jsOutputName = MODULE_NAME, jsOutputName = MODULE_NAME,
icData = icData, icData = icData,
moduleFragment = moduleFragment moduleFragment = moduleFragment,
diagnosticReporter = diagnosticReporter
) { file -> ) { file ->
metadataSerializer.serializeScope(file, module.jsFrontEndResult.bindingContext, moduleFragment.descriptor) metadataSerializer.serializeScope(file, module.jsFrontEndResult.bindingContext, moduleFragment.descriptor)
} }
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner import org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner
import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory 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.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer 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.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.IrModuleToJsTransformer
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -490,12 +492,14 @@ class GenerateIrRuntime {
files: List<KtFile>, files: List<KtFile>,
perFile: Boolean = false perFile: Boolean = false
): String { ): String {
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
val tmpKlibDir = createTempDirectory().also { it.toFile().deleteOnExit() }.toString() val tmpKlibDir = createTempDirectory().also { it.toFile().deleteOnExit() }.toString()
val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, project, false) val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, project, false)
serializeModuleIntoKlib( serializeModuleIntoKlib(
moduleName, moduleName,
configuration, configuration,
IrMessageLogger.None, IrMessageLogger.None,
diagnosticReporter,
files.map(::KtPsiSourceFile), files.map(::KtPsiSourceFile),
tmpKlibDir, tmpKlibDir,
emptyList(), emptyList(),
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.js.klib.generateIrForKlibSerialization import org.jetbrains.kotlin.cli.js.klib.generateIrForKlibSerialization
import org.jetbrains.kotlin.config.CompilerConfiguration 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.*
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsGenerationGranularity import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsGenerationGranularity
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
@@ -108,13 +109,15 @@ abstract class IrAbstractInvalidationTest(
val metadataSerializer = val metadataSerializer =
KlibMetadataIncrementalSerializer(configuration, sourceModule.project, sourceModule.jsFrontEndResult.hasErrors) KlibMetadataIncrementalSerializer(configuration, sourceModule.project, sourceModule.jsFrontEndResult.hasErrors)
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
generateKLib( generateKLib(
sourceModule, sourceModule,
outputKlibFile.canonicalPath, outputKlibFile.canonicalPath,
nopack = false, nopack = false,
jsOutputName = moduleName, jsOutputName = moduleName,
icData = icData, icData = icData,
moduleFragment = moduleFragment moduleFragment = moduleFragment,
diagnosticReporter = diagnosticReporter
) { file -> ) { file ->
metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor) metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor)
} }
@@ -62,6 +62,7 @@ class FirJsKlibBackendFacade(
configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration, configuration,
configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None,
inputArtifact.diagnosticReporter,
inputArtifact.sourceFiles, inputArtifact.sourceFiles,
klibPath = outputFile, klibPath = outputFile,
libraries.map { it.library }, libraries.map { it.library },
@@ -51,6 +51,7 @@ class JsKlibBackendFacade(
configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration, configuration,
configuration.irMessageLogger, configuration.irMessageLogger,
inputArtifact.diagnosticReporter,
inputArtifact.sourceFiles, inputArtifact.sourceFiles,
klibPath = outputFile, klibPath = outputFile,
JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices).keys.toList(), JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices).keys.toList(),
@@ -112,12 +112,19 @@ abstract class AbstractJsPartialLinkageTestCase(private val compilerType: Compil
"-Xir-produce-klib-file", "-Xir-produce-klib-file",
"-ir-output-dir", klibFile.parentFile.absolutePath, "-ir-output-dir", klibFile.parentFile.absolutePath,
"-ir-output-name", moduleName, "-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(), dependencies.toCompilerArgs(),
listOf( listOf(
"-language-version", "2.0", "-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 }, ).takeIf { compilerType.useFir },
kotlinSourceFilePaths kotlinSourceFilePaths
) )
@@ -364,10 +364,7 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
fun testProjectWithExportedNamesClash(gradleVersion: GradleVersion) { fun testProjectWithExportedNamesClash(gradleVersion: GradleVersion) {
project("kotlin-js-invalid-project-with-exported-clash", gradleVersion) { project("kotlin-js-invalid-project-with-exported-clash", gradleVersion) {
build("compileKotlinJs") { build("compileKotlinJs") {
assertOutputContains(""" assertOutputContains("Exporting name 'best' in ES modules may clash")
|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())
} }
} }
} }
@@ -62,6 +62,7 @@ class FirWasmKlibBackendFacade(
configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration, configuration,
configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None,
inputArtifact.diagnosticReporter,
inputArtifact.sourceFiles, inputArtifact.sourceFiles,
klibPath = outputFile, klibPath = outputFile,
libraries.map { it.library }, libraries.map { it.library },