diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 952c7141716..b7c117d82c0 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -8,7 +8,4 @@ - - diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt index 9e08f8566b0..b0515b65302 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt @@ -70,7 +70,7 @@ sealed class ExportedClass : ExportedDeclaration() { abstract val name: String abstract val ir: IrClass abstract val members: List - abstract val superClass: ExportedType? + abstract val superClasses: List abstract val superInterfaces: List abstract val nestedClasses: List } @@ -79,7 +79,7 @@ data class ExportedRegularClass( override val name: String, val isInterface: Boolean = false, val isAbstract: Boolean = false, - override val superClass: ExportedType? = null, + override val superClasses: List = emptyList(), override val superInterfaces: List = emptyList(), val typeParameters: List, override val members: List, @@ -89,7 +89,7 @@ data class ExportedRegularClass( data class ExportedObject( override val name: String, - override val superClass: ExportedType? = null, + override val superClasses: List = emptyList(), override val superInterfaces: List = emptyList(), override val members: List, override val nestedClasses: List, @@ -115,6 +115,7 @@ sealed class ExportedType { object String : Primitive("string") object Throwable : Primitive("Error") object Any : Primitive("any") + object Unknown : Primitive("unknown") object Unit : Primitive("void") object Nothing : Primitive("never") object UniqueSymbol : Primitive("unique symbol") @@ -147,16 +148,16 @@ sealed class ExportedType { class PropertyType(val container: ExportedType, val propertyName: ExportedType) : ExportedType() - class ImplicitlyExportedType(val type: ExportedType) : ExportedType() { + data class ImplicitlyExportedType(val type: ExportedType, val exportedSupertype: ExportedType) : ExportedType() { override fun withNullability(nullable: Boolean) = - ImplicitlyExportedType(type.withNullability(nullable)) + ImplicitlyExportedType(type.withNullability(nullable), exportedSupertype.withNullability(nullable)) } open fun withNullability(nullable: Boolean) = if (nullable) Nullable(this) else this - fun withImplicitlyExported(implicitlyExportedType: Boolean) = - if (implicitlyExportedType) ImplicitlyExportedType(this) else this + fun withImplicitlyExported(implicitlyExportedType: Boolean, exportedSupertype: ExportedType) = + if (implicitlyExportedType) ImplicitlyExportedType(this, exportedSupertype) else this } enum class ExportedVisibility(val keyword: String) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt index 1c36ea1bd83..e87cabca115 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt @@ -24,14 +24,14 @@ import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.keysToMap private const val magicPropertyName = "__doNotUseOrImplementIt" -class ExportModelGenerator( - val context: JsIrBackendContext, - val generateNamespacesForPackages: Boolean -) { +class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespacesForPackages: Boolean) { + private val transitiveExportCollector = TransitiveExportCollector(context) + fun generateExport(file: IrPackageFragment): List { val namespaceFqName = file.fqName val exports = file.declarations.flatMap { declaration -> listOfNotNull(exportDeclaration(declaration)) } @@ -64,10 +64,14 @@ class ExportModelGenerator( } } - private fun exportClass(candidate: IrClass) = if (candidate.isEnumClass) { - exportEnumClass(candidate) - } else { - exportOrdinaryClass(candidate) + private fun exportClass(candidate: IrClass): ExportedDeclaration? { + val superTypes = candidate.defaultType.collectSuperTransitiveHierarchy() + candidate.superTypes + + return if (candidate.isEnumClass) { + exportEnumClass(candidate, superTypes) + } else { + exportOrdinaryClass(candidate, superTypes) + } } private fun exportFunction(function: IrSimpleFunction): ExportedDeclaration? { @@ -203,9 +207,7 @@ class ExportModelGenerator( return Exportability.Allowed } - private fun exportOrdinaryClass( - klass: IrClass - ): ExportedDeclaration? { + private fun exportOrdinaryClass(klass: IrClass, superTypes: Iterable): ExportedDeclaration? { when (val exportability = classExportability(klass)) { is Exportability.Prohibited -> error(exportability.reason) is Exportability.NotNeeded -> return null @@ -213,18 +215,17 @@ class ExportModelGenerator( } } - val (members, nestedClasses) = exportClassDeclarations(klass) + val (members, nestedClasses) = exportClassDeclarations(klass, superTypes) return exportClass( klass, + superTypes, members, nestedClasses ) } - private fun exportEnumClass( - klass: IrClass - ): ExportedDeclaration? { + private fun exportEnumClass(klass: IrClass, superTypes: Iterable): ExportedDeclaration? { when (val exportability = classExportability(klass)) { is Exportability.Prohibited -> error(exportability.reason) is Exportability.NotNeeded -> return null @@ -241,7 +242,7 @@ class ExportModelGenerator( enumEntries .keysToMap(enumEntries::indexOf) - val (members, nestedClasses) = exportClassDeclarations(klass) { candidate -> + val (members, nestedClasses) = exportClassDeclarations(klass, superTypes) { candidate -> val enumExportedMember = exportAsEnumMember(candidate, enumEntriesToOrdinal) enumExportedMember } @@ -253,15 +254,15 @@ class ExportModelGenerator( return exportClass( klass, + superTypes, listOf(privateConstructor) + members, nestedClasses - ).let { - (it as ExportedRegularClass).copy(isAbstract = true) - } + ) } private fun exportClassDeclarations( klass: IrClass, + superTypes: Iterable, specialProcessing: (IrDeclarationWithName) -> ExportedDeclaration? = { null } ): ExportedClassDeclarationsInfo { val members = mutableListOf() @@ -310,8 +311,8 @@ class ExportModelGenerator( } } - if (klass.shouldContainImplementationOfMagicProperty()) { - members.addMagicPropertyForInterfaceImplementation(klass) + if (klass.shouldContainImplementationOfMagicProperty(superTypes)) { + members.addMagicPropertyForInterfaceImplementation(klass, superTypes) } else if (klass.shouldNotBeImplemented()) { members.addMagicInterfaceProperty(klass) } @@ -326,7 +327,7 @@ class ExportModelGenerator( return isInterface && !isExternal } - private fun IrClass.shouldContainImplementationOfMagicProperty(): Boolean { + private fun IrClass.shouldContainImplementationOfMagicProperty(superTypes: Iterable): Boolean { return !isExternal && superTypes.any { val superClass = it.classOrNull?.owner ?: return@any false superClass.isInterface && superClass.isExported(context) @@ -337,8 +338,8 @@ class ExportModelGenerator( add(ExportedProperty(name = magicPropertyName, type = klass.generateTagType(), mutable = false, isMember = true, isField = true)) } - private fun MutableList.addMagicPropertyForInterfaceImplementation(klass: IrClass) { - val superTypesToInheritanceMagicProperty = klass.superTypes.filter { it.shouldAddMagicPropertyOfSuper() } + private fun MutableList.addMagicPropertyForInterfaceImplementation(klass: IrClass, superTypes: Iterable) { + val superTypesToInheritanceMagicProperty = superTypes.filter { it.shouldAddMagicPropertyOfSuper() } if (superTypesToInheritanceMagicProperty.isEmpty()) return @@ -375,20 +376,20 @@ class ExportModelGenerator( private fun exportClass( klass: IrClass, + superTypes: Iterable, members: List, - nestedClasses: List + nestedClasses: List, ): ExportedDeclaration { val typeParameters = klass.typeParameters.map(::exportTypeParameter) - // TODO: Handle non-exported super types + val superClasses = superTypes + .filter { !it.classifierOrFail.isInterface && it.canBeUsedAsSuperTypeOfExportedClasses() } + .map { exportType(it, false) } + .filter { it !is ExportedType.ErrorType } - val superType = klass.superTypes - .firstOrNull { !it.classifierOrFail.isInterface && it.canBeUsedAsSuperTypeOfExportedClasses() } - ?.let { exportType(it).takeIf { it !is ExportedType.ErrorType } } - - val superInterfaces = klass.superTypes + val superInterfaces = superTypes .filter { it.classifierOrFail.isInterface } - .map { exportType(it) } + .map { exportType(it, false) } .filter { it !is ExportedType.ErrorType } val name = klass.getExportedIdentifier() @@ -398,7 +399,7 @@ class ExportModelGenerator( ir = klass, name = name, members = members, - superClass = superType, + superClasses = superClasses, nestedClasses = nestedClasses, superInterfaces = superInterfaces, irGetter = context.mapping.objectToGetInstanceFunction[klass]!! @@ -407,8 +408,8 @@ class ExportModelGenerator( ExportedRegularClass( name = name, isInterface = klass.isInterface, - isAbstract = klass.modality == Modality.ABSTRACT || klass.modality == Modality.SEALED, - superClass = superType, + isAbstract = klass.modality == Modality.ABSTRACT || klass.modality == Modality.SEALED || klass.isEnumClass, + superClasses = superClasses, superInterfaces = superInterfaces, typeParameters = typeParameters, members = members, @@ -418,6 +419,9 @@ class ExportModelGenerator( } } + private fun IrSimpleType.collectSuperTransitiveHierarchy() = + transitiveExportCollector.collectSuperTypesTransitiveHierarchyFor(this) + private fun exportAsEnumMember( candidate: IrDeclarationWithName, enumEntriesToOrdinal: Map @@ -471,8 +475,15 @@ class ExportModelGenerator( private fun exportTypeParameter(typeParameter: IrTypeParameter): ExportedType.TypeParameter { val constraint = typeParameter.superTypes.asSequence() .filter { it != context.irBuiltIns.anyNType } - .map(::exportType) - .filter { it !is ExportedType.ErrorType && it !is ExportedType.ImplicitlyExportedType } + .map { + val exportedType = exportType(it) + if (exportedType is ExportedType.ImplicitlyExportedType && exportedType.exportedSupertype == ExportedType.Primitive.Any) { + exportedType.copy(exportedSupertype = ExportedType.Primitive.Unknown) + } else { + exportedType + } + } + .filter { it !is ExportedType.ErrorType } .toList() return ExportedType.TypeParameter( @@ -487,7 +498,7 @@ class ExportModelGenerator( ) } - private fun exportType(type: IrType): ExportedType { + private fun exportType(type: IrType, shouldCalculateExportedSupertypeForImplicit: Boolean = true): ExportedType { if (type is IrDynamicType) return ExportedType.Primitive.Any @@ -535,6 +546,12 @@ class ExportModelGenerator( val isNonExportedExternal = klass.isExternal && !isExported val name = klass.getFqNameWithJsNameWhenAvailable(!isNonExportedExternal && generateNamespacesForPackages).asString() + val exportedSupertype = runIf(shouldCalculateExportedSupertypeForImplicit && isImplicitlyExported) { + val transitiveExportedType = nonNullType.collectSuperTransitiveHierarchy() + if (transitiveExportedType.isEmpty()) return@runIf null + transitiveExportedType.map(::exportType).reduce(ExportedType::IntersectionType) + } ?: ExportedType.Primitive.Any + when (klass.kind) { ClassKind.ANNOTATION_CLASS, ClassKind.ENUM_ENTRY -> @@ -550,7 +567,7 @@ class ExportModelGenerator( type.arguments.map { exportTypeArgument(it) }, klass ) - }.withImplicitlyExported(isImplicitlyExported) + }.withImplicitlyExported(isImplicitlyExported, exportedSupertype) } else -> error("Unexpected classifier $classifier") @@ -683,7 +700,11 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont } fun IrOverridableDeclaration<*>.isAllowedFakeOverriddenDeclaration(context: JsIrBackendContext): Boolean { - if (this.resolveFakeOverride(allowAbstract = true)?.parentClassOrNull.isExportedInterface(context)) { + val firstExportedRealOverride = runIf(isFakeOverride) { + resolveFakeOverrideOrNull(allowAbstract = true) { it === this || it.parentClassOrNull?.isExported(context) != true } + } + + if (firstExportedRealOverride?.parentClassOrNull.isExportedInterface(context)) { return true } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt index 93fb3476f9b..d36d55771e2 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt @@ -14,6 +14,9 @@ import org.jetbrains.kotlin.ir.util.isObject import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.js.common.isValidES5Identifier import org.jetbrains.kotlin.serialization.js.ModuleKind +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull +import javax.lang.model.type.IntersectionType private const val Nullable = "Nullable" private const val objects = "_objects_" @@ -176,10 +179,7 @@ class ExportModelToTsDeclarations { var t: ExportedType = ExportedType.InlineInterfaceType(members) - if (superClass != null) - t = ExportedType.IntersectionType(t, superClass) - - for (superInterface in superInterfaces) { + for (superInterface in superClasses + superInterfaces) { t = ExportedType.IntersectionType(t, superInterface) } @@ -210,13 +210,13 @@ class ExportModelToTsDeclarations { property.generateTypeScriptString(indent, prefix) } else { val propertyRef = "$objects.$propertyName" - val shouldCreateExtraProperty = members.isNotEmpty() || superInterfaces.isNotEmpty() || superClass != null + val shouldCreateExtraProperty = members.isNotEmpty() || superInterfaces.isNotEmpty() || superClasses.isNotEmpty() val newSuperClass = ExportedType.ClassType(propertyRef, emptyList(), ir).takeIf { shouldCreateExtraProperty } ExportedRegularClass( name = name, isInterface = false, isAbstract = true, - superClass = newSuperClass, + superClasses = listOfNotNull(newSuperClass), superInterfaces = superInterfaces, typeParameters = emptyList(), members = listOf(ExportedConstructor(emptyList(), ExportedVisibility.PRIVATE)), @@ -232,7 +232,7 @@ class ExportModelToTsDeclarations { val keyword = if (isInterface) "interface" else "class" val superInterfacesKeyword = if (isInterface) "extends" else "implements" - val superClassClause = superClass?.let { it.toExtendsClause(indent) } ?: "" + val superClassClause = superClasses.toExtendsClause(indent) val superInterfacesClause = superInterfaces.toImplementsClause(superInterfacesKeyword, indent) val (memberObjects, nestedDeclarations) = nestedClasses.partition { it.couldBeProperty() } @@ -279,12 +279,18 @@ class ExportModelToTsDeclarations { return if (name.isValidES5Identifier()) klassExport + staticsExport else "" } - private fun ExportedType.toExtendsClause(indent: String): String { - val isImplicitlyExportedType = this is ExportedType.ImplicitlyExportedType - val extendsClause = " extends ${toTypeScript(indent, isImplicitlyExportedType)}" - return when { - isImplicitlyExportedType -> " /*$extendsClause */" - else -> extendsClause + private fun List.toExtendsClause(indent: String): String { + if (isEmpty()) return "" + + val implicitlyExportedClasses = filterIsInstance() + val implicitlyExportedClassesString = implicitlyExportedClasses.joinToString(", ") { it.toTypeScript(indent, true) } + + return if (implicitlyExportedClasses.count() == count()) { + " /* extends $implicitlyExportedClassesString */" + } else { + val originallyDefinedSuperClass = implicitlyExportedClassesString.takeIf { it.isNotEmpty() }?.let { "/* $it */ " }.orEmpty() + val transitivelyDefinedSuperClass = firstIsInstance().toTypeScript(indent, false) + " extends $originallyDefinedSuperClass$transitivelyDefinedSuperClass" } } @@ -383,7 +389,12 @@ class ExportModelToTsDeclarations { is ExportedType.LiteralType.NumberLiteralType -> value.toString() is ExportedType.ImplicitlyExportedType -> { val typeString = type.toTypeScript("", true) - if (isInCommentContext) typeString else ExportedType.Primitive.Any.toTypeScript(indent) + "/* $typeString */" + if (isInCommentContext) { + typeString + } else { + val superTypeString = exportedSupertype.toTypeScript(indent) + superTypeString.let { if (exportedSupertype is ExportedType.IntersectionType) "($it)" else it } + "/* $typeString */" + } } is ExportedType.PropertyType -> "${container.toTypeScript(indent, isInCommentContext)}[${ diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/TransitiveExportCollector.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/TransitiveExportCollector.kt new file mode 100644 index 00000000000..636a974c2e2 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/TransitiveExportCollector.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2022 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.export + +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.lower.isBuiltInClass +import org.jetbrains.kotlin.ir.backend.js.lower.isStdLibClass +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* + +private typealias SubstitutionMap = Map + +class TransitiveExportCollector(val context: JsIrBackendContext) { + private val typesCaches = hashMapOf>() + + fun collectSuperTypesTransitiveHierarchyFor(type: IrSimpleType): Set { + val classSymbol = type.classOrNull ?: return emptySet() + + return typesCaches.getOrPut(ClassWithAppliedArguments(classSymbol, type.arguments)) { + type.collectSuperTypesTransitiveHierarchy(type.calculateTypeSubstitutionMap(emptyMap())) + } + } + + private fun IrSimpleType.collectSuperTypesTransitiveHierarchy(typeSubstitutionMap: SubstitutionMap): Set { + val classifier = classOrNull ?: return emptySet() + + return classifier.superTypes() + .flatMap { (it as? IrSimpleType)?.collectTransitiveHierarchy(typeSubstitutionMap) ?: emptySet() } + .toSet() + } + + private fun IrSimpleType.collectTransitiveHierarchy(typeSubstitutionMap: SubstitutionMap): Set { + 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)) + else -> collectSuperTypesTransitiveHierarchy(substitutionMap) + } + } + + private fun IrTypeArgument.getSubstitution(typeSubstitutionMap: SubstitutionMap): IrType { + return when (this) { + is IrType -> substitute(typeSubstitutionMap) + is IrTypeProjection -> type.substitute(typeSubstitutionMap) + else -> error("Unexpected ir type argument") + } + } + + private fun IrSimpleType.calculateTypeSubstitutionMap(typeSubstitutionMap: SubstitutionMap): SubstitutionMap { + val classifier = classOrNull ?: error("Unexpected classifier $classifier for collecting transitive hierarchy") + + return typeSubstitutionMap + classifier.owner.typeParameters.zip(arguments).associate { + it.first.symbol to it.second.getSubstitution(typeSubstitutionMap) + } + } + + private data class ClassWithAppliedArguments(val classSymbol: IrClassSymbol, val appliedArguments: List) +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt index a57c57432bc..39aded1478d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.isChildOf private val BODILESS_BUILTIN_CLASSES = listOf( "kotlin.String", @@ -44,6 +45,9 @@ private val BODILESS_BUILTIN_CLASSES = listOf( fun isBuiltInClass(declaration: IrDeclaration): Boolean = declaration is IrClass && declaration.fqNameWhenAvailable in BODILESS_BUILTIN_CLASSES +fun isStdLibClass(declaration: IrDeclaration): Boolean = + declaration is IrClass && declaration.fqNameWhenAvailable?.isChildOf(JsPackage) != false + private val JsPackage = FqName("kotlin.js") private val JsIntrinsicFqName = FqName("kotlin.js.JsIntrinsic") diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrFakeOverrideUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrFakeOverrideUtils.kt index 2a2d96cc400..b7d263d9c21 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrFakeOverrideUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrFakeOverrideUtils.kt @@ -93,16 +93,24 @@ fun Collection.collectAndFilterRealOverrides(): Set error("all members should be of the same kind, got ${map { it.render() }}") } -// TODO: use this implementation instead of any other fun > T.resolveFakeOverride( allowAbstract: Boolean = false, toSkip: (T) -> Boolean = { false } +): T? = + resolveFakeOverrideOrNull(allowAbstract, toSkip).also { + if (allowAbstract && it == null) { + error("No real overrides for ${this.render()}") + } + } + +// TODO: use this implementation instead of any other +fun > T.resolveFakeOverrideOrNull( + allowAbstract: Boolean = false, + toSkip: (T) -> Boolean = { false } ): T? { if (!isFakeOverride && !toSkip(this)) return this return if (allowAbstract) { - val reals = collectRealOverrides(toSkip) - if (reals.isEmpty()) error("No real overrides for ${this.render()}") - reals.first() + collectRealOverrides(toSkip).firstOrNull() } else { collectRealOverrides(toSkip, { it.modality == Modality.ABSTRACT }) .let { realOverrides -> diff --git a/js/js.translator/testData/typescript-export/functions/functions.d.ts b/js/js.translator/testData/typescript-export/functions/functions.d.ts index 86d3764e475..9324dbe0ad9 100644 --- a/js/js.translator/testData/typescript-export/functions/functions.d.ts +++ b/js/js.translator/testData/typescript-export/functions/functions.d.ts @@ -11,8 +11,8 @@ declare namespace JS_TESTS { function generic1(x: T): T; function generic2(x: Nullable): boolean; function genericWithConstraint(x: T): T; - function genericWithMultipleConstraints(x: T): T; + function genericWithMultipleConstraints */ & RegExpMatchArray & Error>(x: T): T; function generic3(a: A, b: B, c: C, d: D): Nullable; function inlineFun(x: number, callback: (p0: number) => void): void; } -} \ No newline at end of file +} diff --git a/js/js.translator/testData/typescript-export/implicit-export/implicit-export.d.ts b/js/js.translator/testData/typescript-export/implicit-export/implicit-export.d.ts index 15ef3f460fc..b76bd976d26 100644 --- a/js/js.translator/testData/typescript-export/implicit-export/implicit-export.d.ts +++ b/js/js.translator/testData/typescript-export/implicit-export/implicit-export.d.ts @@ -12,7 +12,7 @@ declare namespace JS_TESTS { constructor(value: any/* foo.NonExportedType */); get value(): any/* foo.NonExportedType */; set value(value: any/* foo.NonExportedType */); - increment(t: T): any/* foo.NonExportedType */; + increment(t: T): any/* foo.NonExportedType */; } class B /* extends foo.NonExportedType */ { constructor(v: number); diff --git a/js/js.translator/testData/typescript-export/inheritance/inheritance.d.ts b/js/js.translator/testData/typescript-export/inheritance/inheritance.d.ts index c2b160dfc80..65c6c307d22 100644 --- a/js/js.translator/testData/typescript-export/inheritance/inheritance.d.ts +++ b/js/js.translator/testData/typescript-export/inheritance/inheritance.d.ts @@ -13,6 +13,7 @@ declare namespace JS_TESTS { } } namespace foo { + const fifth: (foo.Third & foo.IA & foo.IG)/* foo.Fifth */; abstract class AC implements foo.I2 { constructor(); get x(): string; @@ -100,5 +101,31 @@ declare namespace JS_TESTS { abstract get baz(): string; readonly __doNotUseOrImplementIt: foo.I3["__doNotUseOrImplementIt"]; } + interface IA { + readonly foo: any; + readonly __doNotUseOrImplementIt: { + readonly "foo.IA": unique symbol; + }; + } + interface IG { + process(value: T): void; + readonly __doNotUseOrImplementIt: { + readonly "foo.IG": unique symbol; + }; + } + class Third extends /* foo.Second */ foo.First { + constructor(); + } + class Sixth extends /* foo.Fifth */ foo.Third implements foo.IA, foo.IG/*, foo.IC */ { + constructor(); + process(value: number): void; + get foo(): number; + readonly __doNotUseOrImplementIt: foo.IA["__doNotUseOrImplementIt"] & foo.IG["__doNotUseOrImplementIt"]; + } + class First { + constructor(); + } + function acceptForthLike & foo.IA)/* foo.Forth */>(forth: T): void; + function acceptMoreGenericForthLike(forth: T): void; } } diff --git a/js/js.translator/testData/typescript-export/inheritance/inheritance.kt b/js/js.translator/testData/typescript-export/inheritance/inheritance.kt index cd484e10328..4d65427d92e 100644 --- a/js/js.translator/testData/typescript-export/inheritance/inheritance.kt +++ b/js/js.translator/testData/typescript-export/inheritance/inheritance.kt @@ -163,3 +163,53 @@ enum class EC : I3 { override fun bay(): String = "bay" } + +// Save hierarhy + +@JsExport +interface IA { + val foo: Any +} + +@JsExport +interface IG { + fun process(value: T): Unit +} + +interface IB : IA + +interface IC : IB { + override val foo: Any +} + +interface ID : IC { + override val foo: Int +} + +@JsExport +open class Third: Second() + +open class Forth: Third(), IB, ID { + override val foo: Int = 42 +} + +open class Fifth: Forth(), IG { + override fun process(value: B) {} +} + +@JsExport +class Sixth: Fifth(), IC + +@JsExport +open class First + +open class Second: First() + +@JsExport +fun > acceptForthLike(forth: T) {} + +@JsExport +fun acceptMoreGenericForthLike(forth: T) where T: IB, T: IC, T: Second {} + +@JsExport +val fifth = Fifth() diff --git a/js/js.translator/testData/typescript-export/methods/methods.d.ts b/js/js.translator/testData/typescript-export/methods/methods.d.ts index 98791c2670f..d2264326123 100644 --- a/js/js.translator/testData/typescript-export/methods/methods.d.ts +++ b/js/js.translator/testData/typescript-export/methods/methods.d.ts @@ -13,7 +13,7 @@ declare namespace JS_TESTS { generic1(x: T): T; generic2(x: Nullable): boolean; genericWithConstraint(x: T): T; - genericWithMultipleConstraints(x: T): T; + genericWithMultipleConstraints */ & RegExpMatchArray & Error>(x: T): T; generic3(a: A, b: B, c: C, d: D): Nullable; inlineFun(x: number, callback: (p0: number) => void): void; }