[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:
@@ -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,
|
||||||
|
|||||||
+37
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -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>
|
||||||
+47
@@ -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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+57
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+55
@@ -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,
|
||||||
|
|||||||
+48
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-2
@@ -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
|
||||||
|
|
||||||
@@ -24,4 +23,4 @@ class JsIrFileMetadata(val exportedNames: List<String>) : IrFileSerializer.FileB
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-42
@@ -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
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -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()
|
||||||
|
^
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
+9
-2
@@ -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
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-4
@@ -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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -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 },
|
||||||
|
|||||||
Reference in New Issue
Block a user