[K/JS] feat: add logic under the flag for strict implicit export generating inside d.ts files.
This commit is contained in:
+7
@@ -207,6 +207,13 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
|
||||
)
|
||||
var generateDts: Boolean by FreezableVar(false)
|
||||
|
||||
|
||||
@Argument(
|
||||
value = "-Xstrict-implicit-export-types",
|
||||
description = "Generate strict types for implicitly exported entities inside d.ts files. Available in IR backend only."
|
||||
)
|
||||
var strictImplicitExportType: Boolean by FreezableVar(false)
|
||||
|
||||
@GradleOption(DefaultValues.BooleanTrueDefault::class)
|
||||
@Argument(value = "-Xtyped-arrays", description = "Translate primitive arrays to JS typed arrays")
|
||||
var typedArrays: Boolean by FreezableVar(true)
|
||||
|
||||
@@ -503,6 +503,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
|
||||
configuration.put(JSConfigurationKeys.FRIEND_PATHS_DISABLED, arguments.friendModulesDisabled)
|
||||
|
||||
configuration.put(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT, arguments.strictImplicitExportType)
|
||||
|
||||
|
||||
val friendModules = arguments.friendModules
|
||||
if (!arguments.friendModulesDisabled && friendModules != null) {
|
||||
val friendPaths = friendModules
|
||||
|
||||
@@ -311,6 +311,8 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
||||
val doNotIntrinsifyAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("DoNotIntrinsify"))
|
||||
val jsFunAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsFun"))
|
||||
|
||||
val jsImplicitExportAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsImplicitExport"))
|
||||
|
||||
// TODO move CharSequence-related stiff to IntrinsifyCallsLowering
|
||||
val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence")))
|
||||
val charSequenceLengthPropertyGetterSymbol by context.lazy2 {
|
||||
|
||||
@@ -798,6 +798,12 @@ private val escapedIdentifiersLowering = makeBodyLoweringPhase(
|
||||
description = "Convert global variables with invalid names access to globalThis member expression"
|
||||
)
|
||||
|
||||
private val implicitlyExportedDeclarationsMarkingLowering = makeDeclarationTransformerPhase(
|
||||
::ImplicitlyExportedDeclarationsMarkingLowering,
|
||||
name = "ImplicitlyExportedDeclarationsMarkingLowering",
|
||||
description = "Add @JsImplicitExport annotation to declarations which are not exported but are used inside other exported declarations as a type"
|
||||
)
|
||||
|
||||
private val cleanupLoweringPhase = makeBodyLoweringPhase(
|
||||
{ CleanupLowering() },
|
||||
name = "CleanupLowering",
|
||||
@@ -920,6 +926,7 @@ val loweringList = listOf<Lowering>(
|
||||
captureStackTraceInThrowablesPhase,
|
||||
callsLoweringPhase,
|
||||
escapedIdentifiersLowering,
|
||||
implicitlyExportedDeclarationsMarkingLowering,
|
||||
cleanupLoweringPhase,
|
||||
// Currently broken due to static members lowering making single-open-class
|
||||
// files non-recognizable as single-class files
|
||||
|
||||
@@ -61,7 +61,6 @@ class ExportedProperty(
|
||||
val irSetter: IrFunction? = null,
|
||||
) : ExportedDeclaration()
|
||||
|
||||
|
||||
// TODO: Cover all cases with frontend and disable error declarations
|
||||
class ErrorDeclaration(val message: String) : ExportedDeclaration()
|
||||
|
||||
|
||||
+72
-19
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
@@ -53,7 +55,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
|
||||
private fun exportDeclaration(declaration: IrDeclaration): ExportedDeclaration? {
|
||||
val candidate = getExportCandidate(declaration) ?: return null
|
||||
if (!shouldDeclarationBeExported(candidate, context)) return null
|
||||
if (!shouldDeclarationBeExportedImplicitlyOrExplicitly(candidate, context)) return null
|
||||
|
||||
return when (candidate) {
|
||||
is IrSimpleFunction -> exportFunction(candidate)
|
||||
@@ -74,9 +76,10 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun exportFunction(function: IrSimpleFunction): ExportedDeclaration? {
|
||||
return when (val exportability = functionExportability(function)) {
|
||||
is Exportability.NotNeeded -> null
|
||||
is Exportability.NotNeeded, is Exportability.Implicit -> null
|
||||
is Exportability.Prohibited -> ErrorDeclaration(exportability.reason)
|
||||
is Exportability.Allowed -> {
|
||||
val parent = function.parent
|
||||
@@ -201,18 +204,44 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
}
|
||||
|
||||
if (klass.isJsImplicitExport()) {
|
||||
return Exportability.Implicit
|
||||
}
|
||||
|
||||
if (klass.isSingleFieldValueClass)
|
||||
return Exportability.Prohibited("Inline class ${klass.fqNameWhenAvailable}")
|
||||
|
||||
return Exportability.Allowed
|
||||
}
|
||||
|
||||
private fun exportDeclarationImplicitly(klass: IrClass, superTypes: Iterable<IrType>): ExportedDeclaration {
|
||||
val typeParameters = klass.typeParameters.map(::exportTypeParameter)
|
||||
val superInterfaces = superTypes
|
||||
.filter { (it.classifierOrFail.owner as? IrDeclaration)?.isExportedImplicitlyOrExplicitly(context) ?: false }
|
||||
.map { exportType(it) }
|
||||
.filter { it !is ExportedType.ErrorType }
|
||||
|
||||
val name = klass.getExportedIdentifier()
|
||||
val (members, nestedClasses) = exportClassDeclarations(klass, superTypes)
|
||||
return ExportedRegularClass(
|
||||
name = name,
|
||||
isInterface = true,
|
||||
isAbstract = false,
|
||||
superClasses = emptyList(),
|
||||
superInterfaces = superInterfaces,
|
||||
typeParameters = typeParameters,
|
||||
members = members,
|
||||
nestedClasses = nestedClasses,
|
||||
ir = klass
|
||||
)
|
||||
}
|
||||
|
||||
private fun exportOrdinaryClass(klass: IrClass, superTypes: Iterable<IrType>): ExportedDeclaration? {
|
||||
when (val exportability = classExportability(klass)) {
|
||||
is Exportability.Prohibited -> error(exportability.reason)
|
||||
is Exportability.NotNeeded -> return null
|
||||
Exportability.Allowed -> {
|
||||
}
|
||||
Exportability.NotNeeded -> return null
|
||||
Exportability.Implicit -> return exportDeclarationImplicitly(klass, superTypes)
|
||||
Exportability.Allowed -> {}
|
||||
}
|
||||
|
||||
val (members, nestedClasses) = exportClassDeclarations(klass, superTypes)
|
||||
@@ -228,9 +257,9 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
private fun exportEnumClass(klass: IrClass, superTypes: Iterable<IrType>): ExportedDeclaration? {
|
||||
when (val exportability = classExportability(klass)) {
|
||||
is Exportability.Prohibited -> error(exportability.reason)
|
||||
is Exportability.NotNeeded -> return null
|
||||
Exportability.Allowed -> {
|
||||
}
|
||||
Exportability.NotNeeded -> return null
|
||||
Exportability.Implicit -> return exportDeclarationImplicitly(klass, superTypes)
|
||||
Exportability.Allowed -> {}
|
||||
}
|
||||
|
||||
val enumEntries = klass
|
||||
@@ -267,10 +296,12 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
): ExportedClassDeclarationsInfo {
|
||||
val members = mutableListOf<ExportedDeclaration>()
|
||||
val nestedClasses = mutableListOf<ExportedClass>()
|
||||
val isImplicitlyExportedClass = klass.isJsImplicitExport()
|
||||
|
||||
for (declaration in klass.declarations) {
|
||||
val candidate = getExportCandidate(declaration) ?: continue
|
||||
if (!shouldDeclarationBeExported(candidate, context)) continue
|
||||
if (isImplicitlyExportedClass && candidate !is IrClass) continue
|
||||
if (!shouldDeclarationBeExportedImplicitlyOrExplicitly(candidate, context)) continue
|
||||
|
||||
val processingResult = specialProcessing(candidate)
|
||||
if (processingResult != null) {
|
||||
@@ -324,13 +355,13 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
|
||||
private fun IrClass.shouldNotBeImplemented(): Boolean {
|
||||
return isInterface && !isExternal
|
||||
return isInterface && !isExternal || isJsImplicitExport()
|
||||
}
|
||||
|
||||
private fun IrClass.shouldContainImplementationOfMagicProperty(superTypes: Iterable<IrType>): Boolean {
|
||||
return !isExternal && superTypes.any {
|
||||
val superClass = it.classOrNull?.owner ?: return@any false
|
||||
superClass.isInterface && superClass.isExported(context)
|
||||
superClass.isInterface && superClass.isExported(context) || superClass.isJsImplicitExport()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,11 +370,13 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
|
||||
private fun MutableList<ExportedDeclaration>.addMagicPropertyForInterfaceImplementation(klass: IrClass, superTypes: Iterable<IrType>) {
|
||||
val superTypesToInheritanceMagicProperty = superTypes.filter { it.shouldAddMagicPropertyOfSuper() }
|
||||
val allSuperTypesWithMagicProperty = superTypes.filter { it.shouldAddMagicPropertyOfSuper() }
|
||||
|
||||
if (superTypesToInheritanceMagicProperty.isEmpty()) return
|
||||
if (allSuperTypesWithMagicProperty.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val intersectionOfTypes = superTypesToInheritanceMagicProperty
|
||||
val intersectionOfTypes = allSuperTypesWithMagicProperty
|
||||
.map { ExportedType.PropertyType(exportType(it), ExportedType.LiteralType.StringLiteralType(magicPropertyName)) }
|
||||
.reduce(ExportedType::IntersectionType)
|
||||
.let { if (klass.shouldNotBeImplemented()) ExportedType.IntersectionType(klass.generateTagType(), it) else it }
|
||||
@@ -356,8 +389,11 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
|
||||
private fun IrClass.isOwnMagicPropertyAdded(): Boolean {
|
||||
if (isJsImplicitExport()) return true
|
||||
if (!isExported(context)) return false
|
||||
return isInterface && !isExternal || superTypes.any { it.classOrNull?.owner?.isOwnMagicPropertyAdded() ?: false }
|
||||
return isInterface && !isExternal || superTypes.any {
|
||||
it.classOrNull?.owner?.isOwnMagicPropertyAdded() == true
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.generateTagType(): ExportedType {
|
||||
@@ -388,7 +424,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
.filter { it !is ExportedType.ErrorType }
|
||||
|
||||
val superInterfaces = superTypes
|
||||
.filter { it.classifierOrFail.isInterface }
|
||||
.filter { it.shouldPresentInsideImplementsClause() }
|
||||
.map { exportType(it, false) }
|
||||
.filter { it !is ExportedType.ErrorType }
|
||||
|
||||
@@ -419,9 +455,14 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrSimpleType.collectSuperTransitiveHierarchy() =
|
||||
private fun IrSimpleType.collectSuperTransitiveHierarchy(): Set<IrType> =
|
||||
transitiveExportCollector.collectSuperTypesTransitiveHierarchyFor(this)
|
||||
|
||||
private fun IrType.shouldPresentInsideImplementsClause(): Boolean {
|
||||
val classifier = classifierOrFail
|
||||
return classifier.isInterface || (classifier.owner as? IrDeclaration)?.isJsImplicitExport() == true
|
||||
}
|
||||
|
||||
private fun exportAsEnumMember(
|
||||
candidate: IrDeclarationWithName,
|
||||
enumEntriesToOrdinal: Map<IrEnumEntry, Int>
|
||||
@@ -460,7 +501,9 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
|
||||
private fun IrType.canBeUsedAsSuperTypeOfExportedClasses(): Boolean =
|
||||
!this.isAny() && classifierOrNull != context.irBuiltIns.enumClass
|
||||
!isAny() &&
|
||||
classifierOrNull != context.irBuiltIns.enumClass &&
|
||||
(classifierOrNull?.owner as? IrDeclaration)?.isJsImplicitExport() != true
|
||||
|
||||
private fun exportTypeArgument(type: IrTypeArgument): ExportedType {
|
||||
if (type is IrTypeProjection)
|
||||
@@ -541,7 +584,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
|
||||
classifier is IrClassSymbol -> {
|
||||
val klass = classifier.owner
|
||||
val isExported = klass.isExported(context)
|
||||
val isExported = klass.isExportedImplicitlyOrExplicitly(context)
|
||||
val isImplicitlyExported = !isExported && !klass.isExternal
|
||||
val isNonExportedExternal = klass.isExternal && !isExported
|
||||
val name = klass.getFqNameWithJsNameWhenAvailable(!isNonExportedExternal && generateNamespacesForPackages).asString()
|
||||
@@ -630,6 +673,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
sealed class Exportability {
|
||||
object Allowed : Exportability()
|
||||
object NotNeeded : Exportability()
|
||||
object Implicit : Exportability()
|
||||
class Prohibited(val reason: String) : Exportability()
|
||||
}
|
||||
|
||||
@@ -670,6 +714,10 @@ private fun getExportCandidate(declaration: IrDeclaration): IrDeclarationWithNam
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun shouldDeclarationBeExportedImplicitlyOrExplicitly(declaration: IrDeclarationWithName, context: JsIrBackendContext): Boolean {
|
||||
return declaration.isJsImplicitExport() || shouldDeclarationBeExported(declaration, context)
|
||||
}
|
||||
|
||||
private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, context: JsIrBackendContext): Boolean {
|
||||
if (context.additionalExportedDeclarationNames.contains(declaration.fqNameWhenAvailable))
|
||||
return true
|
||||
@@ -727,6 +775,11 @@ fun IrDeclaration.isExported(context: JsIrBackendContext): Boolean {
|
||||
return shouldDeclarationBeExported(candidate, context)
|
||||
}
|
||||
|
||||
fun IrDeclaration.isExportedImplicitlyOrExplicitly(context: JsIrBackendContext): Boolean {
|
||||
val candidate = getExportCandidate(this) ?: return false
|
||||
return shouldDeclarationBeExportedImplicitlyOrExplicitly(candidate, context)
|
||||
}
|
||||
|
||||
private fun DescriptorVisibility.toExportedVisibility() =
|
||||
when (this) {
|
||||
DescriptorVisibilities.PROTECTED -> ExportedVisibility.PROTECTED
|
||||
|
||||
+19
-2
@@ -12,6 +12,10 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isJsImplicitExport
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.superTypes
|
||||
|
||||
private typealias SubstitutionMap = Map<IrTypeParameterSymbol, IrType>
|
||||
|
||||
@@ -34,13 +38,26 @@ class TransitiveExportCollector(val context: JsIrBackendContext) {
|
||||
.toSet()
|
||||
}
|
||||
|
||||
private fun IrSimpleType.findNearestExportedClass(typeSubstitutionMap: SubstitutionMap): IrSimpleType? {
|
||||
val classifier = classifier as? IrClassSymbol ?: return null
|
||||
if (classifier.owner.isExported(context)) return substitute(typeSubstitutionMap) as IrSimpleType
|
||||
|
||||
return classifier.superTypes()
|
||||
.firstNotNullOfOrNull { (it as? IrSimpleType)?.findNearestExportedClass(typeSubstitutionMap) }
|
||||
}
|
||||
|
||||
private fun IrSimpleType.collectTransitiveHierarchy(typeSubstitutionMap: SubstitutionMap): Set<IrType> {
|
||||
val owner = classifier.owner as? IrClass ?: return emptySet()
|
||||
val substitutionMap = calculateTypeSubstitutionMap(typeSubstitutionMap)
|
||||
|
||||
return when {
|
||||
isBuiltInClass(owner) || isStdLibClass(owner) -> emptySet()
|
||||
owner.isExported(context) -> setOf(substitute(typeSubstitutionMap))
|
||||
owner.isExported(context) -> setOf(substitute(substitutionMap))
|
||||
owner.isJsImplicitExport() -> setOfNotNull(
|
||||
substitute(typeSubstitutionMap),
|
||||
takeIf { !owner.isInterface }?.findNearestExportedClass(substitutionMap)
|
||||
)
|
||||
|
||||
else -> collectSuperTypesTransitiveHierarchy(substitutionMap)
|
||||
}
|
||||
}
|
||||
@@ -62,4 +79,4 @@ class TransitiveExportCollector(val context: JsIrBackendContext) {
|
||||
}
|
||||
|
||||
private data class ClassWithAppliedArguments(val classSymbol: IrClassSymbol, val appliedArguments: List<IrTypeArgument>)
|
||||
}
|
||||
}
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isJsImplicitExport
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
|
||||
class ImplicitlyExportedDeclarationsMarkingLowering(private val context: JsIrBackendContext) : DeclarationTransformer {
|
||||
private val strictImplicitExport = context.configuration.getBoolean(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT)
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (!strictImplicitExport || !declaration.isExported(context)) return null
|
||||
|
||||
val implicitlyExportedDeclarations = when (declaration) {
|
||||
is IrFunction -> declaration.collectImplicitlyExportedDeclarations()
|
||||
is IrClass -> declaration.collectImplicitlyExportedDeclarations()
|
||||
is IrProperty -> declaration.collectImplicitlyExportedDeclarations()
|
||||
else -> emptySet()
|
||||
}
|
||||
|
||||
implicitlyExportedDeclarations.forEach { it.markWithJsImplicitExport() }
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun IrClass.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
|
||||
return typeParameters
|
||||
.flatMap { it.superTypes }.toSet()
|
||||
.flatMap { it.collectImplicitlyExportedDeclarations() }.toSet()
|
||||
}
|
||||
|
||||
|
||||
private fun IrFunction.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
|
||||
val types = buildSet {
|
||||
add(returnType)
|
||||
addAll(valueParameters.map { it.type })
|
||||
addAll(typeParameters.flatMap { it.superTypes })
|
||||
}
|
||||
|
||||
return types.flatMap { it.collectImplicitlyExportedDeclarations() }.toSet()
|
||||
}
|
||||
|
||||
private fun IrProperty.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
|
||||
val getterImplicitlyExportedDeclarations = getter?.collectImplicitlyExportedDeclarations() ?: emptySet()
|
||||
val setterImplicitlyExportedDeclarations = setter?.collectImplicitlyExportedDeclarations() ?: emptySet()
|
||||
val fieldImplicitlyExportedDeclarations = backingField?.type?.collectImplicitlyExportedDeclarations() ?: emptySet()
|
||||
|
||||
return getterImplicitlyExportedDeclarations + setterImplicitlyExportedDeclarations + fieldImplicitlyExportedDeclarations
|
||||
}
|
||||
|
||||
private fun IrType.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
|
||||
if (this is IrDynamicType || this !is IrSimpleType)
|
||||
return emptySet()
|
||||
|
||||
val nonNullType = makeNotNull() as IrSimpleType
|
||||
val classifier = nonNullType.classifier
|
||||
|
||||
return when {
|
||||
nonNullType.isPrimitiveType() || nonNullType.isPrimitiveArray() || nonNullType.isAny() || nonNullType.isUnit() -> emptySet()
|
||||
classifier is IrTypeParameterSymbol -> classifier.owner.superTypes.flatMap { it.collectImplicitlyExportedDeclarations() }
|
||||
.toSet()
|
||||
|
||||
classifier is IrClassSymbol -> setOfNotNull(classifier.owner.takeIf { it.shouldBeMarkedWithImplicitExport() })
|
||||
else -> emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrDeclaration.shouldBeMarkedWithImplicitExport(): Boolean {
|
||||
return this is IrClass && !isExternal && !isExported(context) && !isJsImplicitExport()
|
||||
}
|
||||
|
||||
private fun IrDeclaration.markWithJsImplicitExport() {
|
||||
val jsImplicitExportCtor = context.intrinsics.jsImplicitExportAnnotationSymbol.constructors.single()
|
||||
annotations += context.createIrBuilder(symbol).irCall(jsImplicitExportCtor)
|
||||
|
||||
parentClassOrNull?.takeIf { it.shouldBeMarkedWithImplicitExport() }?.markWithJsImplicitExport()
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ object JsAnnotations {
|
||||
val jsNameFqn = FqName("kotlin.js.JsName")
|
||||
val jsQualifierFqn = FqName("kotlin.js.JsQualifier")
|
||||
val jsExportFqn = FqName("kotlin.js.JsExport")
|
||||
val jsImplicitExportFqn = FqName("kotlin.js.JsImplicitExport")
|
||||
val jsNativeGetter = FqName("kotlin.js.nativeGetter")
|
||||
val jsNativeSetter = FqName("kotlin.js.nativeSetter")
|
||||
val jsNativeInvoke = FqName("kotlin.js.nativeInvoke")
|
||||
@@ -34,6 +35,10 @@ object JsAnnotations {
|
||||
fun IrConstructorCall.getSingleConstStringArgument() =
|
||||
(getValueArgument(0) as IrConst<String>).value
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun IrConstructorCall.getSingleConstBooleanArgument() =
|
||||
(getValueArgument(0) as IrConst<Boolean>).value
|
||||
|
||||
fun IrAnnotationContainer.getJsModule(): String? =
|
||||
getAnnotation(JsAnnotations.jsModuleFqn)?.getSingleConstStringArgument()
|
||||
|
||||
@@ -58,6 +63,9 @@ fun IrAnnotationContainer.getJsFunAnnotation(): String? =
|
||||
fun IrAnnotationContainer.isJsExport(): Boolean =
|
||||
hasAnnotation(JsAnnotations.jsExportFqn)
|
||||
|
||||
fun IrAnnotationContainer.isJsImplicitExport(): Boolean =
|
||||
hasAnnotation(JsAnnotations.jsImplicitExportFqn)
|
||||
|
||||
fun IrAnnotationContainer.isJsNativeGetter(): Boolean = hasAnnotation(JsAnnotations.jsNativeGetter)
|
||||
|
||||
fun IrAnnotationContainer.isJsNativeSetter(): Boolean = hasAnnotation(JsAnnotations.jsNativeSetter)
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ where advanced options include:
|
||||
-Xmetadata-only Generate *.meta.js and *.kjsm files only
|
||||
-Xpartial-linkage Allow unlinked symbols
|
||||
-Xrepositories=<path> Paths to additional places where libraries could be found
|
||||
-Xstrict-implicit-export-types Generate strict types for implicitly exported entities inside d.ts files. Available in IR backend only.
|
||||
-Xtyped-arrays Translate primitive arrays to JS typed arrays
|
||||
-Xwasm Use experimental WebAssembly compiler backend
|
||||
-Xwasm-debug-info Add debug info to WebAssembly compiled module
|
||||
|
||||
+5
@@ -117,6 +117,11 @@ object JsEnvironmentConfigurationDirectives : SimpleDirectivesContainer() {
|
||||
applicability = DirectiveApplicability.Global
|
||||
)
|
||||
|
||||
val GENERATE_STRICT_IMPLICIT_EXPORT by directive(
|
||||
description = "enable strict implicitly exported entities types inside d.ts files",
|
||||
applicability = DirectiveApplicability.Global
|
||||
)
|
||||
|
||||
val SAFE_EXTERNAL_BOOLEAN by directive(
|
||||
description = "",
|
||||
applicability = DirectiveApplicability.Global
|
||||
|
||||
+5
@@ -125,6 +125,11 @@ fun TargetPlatform.platformToEnvironmentConfigFiles() = when {
|
||||
fun createCompilerConfiguration(module: TestModule, configurators: List<AbstractEnvironmentConfigurator>): CompilerConfiguration {
|
||||
val configuration = CompilerConfiguration()
|
||||
configuration[CommonConfigurationKeys.MODULE_NAME] = module.name
|
||||
|
||||
if (JsEnvironmentConfigurationDirectives.GENERATE_STRICT_IMPLICIT_EXPORT in module.directives) {
|
||||
configuration.put(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT, true)
|
||||
}
|
||||
|
||||
if (module.frontendKind == FrontendKinds.FIR) {
|
||||
configuration[CommonConfigurationKeys.USE_FIR] = true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user