diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt index 22fdeaabc0b..41f8802413c 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt @@ -59,7 +59,7 @@ class TypeParameterStub( val upperBound: StubType? = null ) { fun getStubType(nullable: Boolean) = - TypeParameterType(name, nullable = nullable) + TypeParameterType(name, nullable = nullable, typeParameterDeclaration = this) } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt index c60d7fbbba1..36d8224e962 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.native.interop.gen import kotlinx.metadata.* import kotlinx.metadata.klib.* +import org.jetbrains.kotlin.metadata.serialization.Interner import org.jetbrains.kotlin.utils.addIfNotNull class StubIrMetadataEmitter( @@ -69,7 +70,8 @@ internal class ModuleMetadataEmitter( */ private data class VisitingContext( val container: StubContainer? = null, - val uniqIds: StubIrUniqIdProvider + val uniqIds: StubIrUniqIdProvider, + val typeParametersInterner: Interner = Interner() ) private val visitor = object : StubIrVisitor { @@ -79,41 +81,47 @@ internal class ModuleMetadataEmitter( } override fun visitTypealias(element: TypealiasStub, data: VisitingContext): KmTypeAlias = - KmTypeAlias(element.flags, element.alias.topLevelName).also { km -> - km.uniqId = data.uniqIds.uniqIdForTypeAlias(element) - km.underlyingType = element.aliasee.map(shouldExpandTypeAliases = false) - km.expandedType = element.aliasee.map() - } + with (MappingExtensions(data.typeParametersInterner)) { + KmTypeAlias(element.flags, element.alias.topLevelName).also { km -> + km.uniqId = data.uniqIds.uniqIdForTypeAlias(element) + km.underlyingType = element.aliasee.map(shouldExpandTypeAliases = false) + km.expandedType = element.aliasee.map() + } + } override fun visitFunction(element: FunctionStub, data: VisitingContext) = - KmFunction(element.flags, element.name).also { km -> - element.annotations.mapTo(km.annotations, AnnotationStub::map) - km.returnType = element.returnType.map() - element.parameters.mapTo(km.valueParameters, FunctionParameterStub::map) - element.typeParameters.mapTo(km.typeParameters, TypeParameterStub::map) - km.uniqId = data.uniqIds.uniqIdForFunction(element) - } + with (MappingExtensions(data.typeParametersInterner)) { + KmFunction(element.flags, element.name).also { km -> + element.typeParameters.mapTo(km.typeParameters) { it.map() } + element.parameters.mapTo(km.valueParameters) { it.map() } + element.annotations.mapTo(km.annotations) { it.map() } + km.returnType = element.returnType.map() + km.uniqId = data.uniqIds.uniqIdForFunction(element) + } + } override fun visitProperty(element: PropertyStub, data: VisitingContext) = - KmProperty(element.flags, element.name, element.getterFlags, element.setterFlags).also { km -> - element.annotations.mapTo(km.annotations, AnnotationStub::map) - km.uniqId = data.uniqIds.uniqIdForProperty(element) - km.returnType = element.type.map() - if (element.kind is PropertyStub.Kind.Var) { - val setter = element.kind.setter - setter.annotations.mapTo(km.setterAnnotations, AnnotationStub::map) - // TODO: Maybe it's better to explicitly add setter parameter in stub. - km.setterParameter = FunctionParameterStub("value", element.type).map() + with (MappingExtensions(data.typeParametersInterner)) { + KmProperty(element.flags, element.name, element.getterFlags, element.setterFlags).also { km -> + element.annotations.mapTo(km.annotations) { it.map() } + km.uniqId = data.uniqIds.uniqIdForProperty(element) + km.returnType = element.type.map() + if (element.kind is PropertyStub.Kind.Var) { + val setter = element.kind.setter + setter.annotations.mapTo(km.setterAnnotations) { it.map() } + // TODO: Maybe it's better to explicitly add setter parameter in stub. + km.setterParameter = FunctionParameterStub("value", element.type).map() + } + km.getterAnnotations += when (element.kind) { + is PropertyStub.Kind.Val -> element.kind.getter.annotations.map { it.map() } + is PropertyStub.Kind.Var -> element.kind.getter.annotations.map { it.map() } + is PropertyStub.Kind.Constant -> emptyList() + } + if (element.kind is PropertyStub.Kind.Constant) { + km.compileTimeValue = element.kind.constant.mapToAnnotationArgument() + } + } } - km.getterAnnotations += when (element.kind) { - is PropertyStub.Kind.Val -> element.kind.getter.annotations.map(AnnotationStub::map) - is PropertyStub.Kind.Var -> element.kind.getter.annotations.map(AnnotationStub::map) - is PropertyStub.Kind.Constant -> emptyList() - } - if (element.kind is PropertyStub.Kind.Constant) { - km.compileTimeValue = element.kind.constant.mapToAnnotationArgument() - } - } override fun visitConstructor(constructorStub: ConstructorStub, data: VisitingContext) { // TODO("not implemented") @@ -129,223 +137,289 @@ internal class ModuleMetadataEmitter( } } -private val FunctionStub.flags: Flags - get() = listOfNotNull( - Flag.Common.IS_PUBLIC, - Flag.Function.IS_EXTERNAL, - Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, - Flag.IS_FINAL.takeIf { modality == MemberStubModality.FINAL }, - Flag.IS_OPEN.takeIf { modality == MemberStubModality.OPEN }, - Flag.IS_ABSTRACT.takeIf { modality == MemberStubModality.ABSTRACT } - ).let { flagsOf(*it.toTypedArray()) } - -private val Classifier.fqNameSerialized: String - get() = buildString { - if (pkg.isNotEmpty()) { - append(pkg.replace('.', '/')) - append('/') - } - // Nested classes should dot-separated. - append(relativeFqName) - } - -private val PropertyStub.flags: Flags - get() = listOfNotNull( - Flag.IS_PUBLIC, - Flag.Property.IS_DECLARATION, - Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, - Flag.IS_FINAL.takeIf { modality == MemberStubModality.FINAL }, - when (kind) { - is PropertyStub.Kind.Val -> null - is PropertyStub.Kind.Var -> Flag.Property.IS_VAR - is PropertyStub.Kind.Constant -> Flag.Property.IS_CONST - }, - when (kind) { - is PropertyStub.Kind.Constant -> null - is PropertyStub.Kind.Val, - is PropertyStub.Kind.Var -> Flag.Property.HAS_GETTER - }, - when (kind) { - is PropertyStub.Kind.Constant -> null - is PropertyStub.Kind.Val -> null - is PropertyStub.Kind.Var -> Flag.Property.HAS_SETTER - } - ).let { flagsOf(*it.toTypedArray()) } - -private val PropertyStub.getterFlags: Flags - get() = when (kind) { - is PropertyStub.Kind.Val -> kind.getter.flags - is PropertyStub.Kind.Var -> kind.getter.flags - is PropertyStub.Kind.Constant -> flagsOf() - } - -private val PropertyAccessor.Getter.flags: Flags - get() = listOfNotNull( - Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, - Flag.IS_PUBLIC, - Flag.IS_FINAL, - Flag.PropertyAccessor.IS_EXTERNAL.takeIf { this is PropertyAccessor.Getter.ExternalGetter } - ).let { flagsOf(*it.toTypedArray()) } - -private val PropertyStub.setterFlags: Flags - get() = if (kind !is PropertyStub.Kind.Var) flagsOf() - else kind.setter.flags - -private val PropertyAccessor.Setter.flags: Flags - get() = listOfNotNull( - Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, - Flag.IS_PUBLIC, - Flag.IS_FINAL, - Flag.PropertyAccessor.IS_EXTERNAL.takeIf { this is PropertyAccessor.Setter.ExternalSetter } - ).let { flagsOf(*it.toTypedArray()) } - -private val StubType.flags: Flags - get() = listOfNotNull( - Flag.Type.IS_NULLABLE.takeIf { nullable } - ).let { flagsOf(*it.toTypedArray()) } - -private val TypealiasStub.flags: Flags - get() = listOfNotNull( - Flag.IS_PUBLIC - ).let { flagsOf(*it.toTypedArray()) } - -private val FunctionParameterStub.flags: Flags - get() = listOfNotNull( - Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() } - ).let { flagsOf(*it.toTypedArray()) } - -private fun AnnotationStub.map(): KmAnnotation { - val args = when (this) { - AnnotationStub.ObjC.ConsumesReceiver -> TODO() - AnnotationStub.ObjC.ReturnsRetained -> TODO() - is AnnotationStub.ObjC.Method -> TODO() - is AnnotationStub.ObjC.Factory -> TODO() - AnnotationStub.ObjC.Consumed -> TODO() - is AnnotationStub.ObjC.Constructor -> TODO() - is AnnotationStub.ObjC.ExternalClass -> TODO() - AnnotationStub.CCall.CString -> mapOf() - AnnotationStub.CCall.WCString -> mapOf() - is AnnotationStub.CCall.Symbol -> - mapOf("id" to KmAnnotationArgument.StringValue(symbolName)) - is AnnotationStub.CStruct -> TODO() - is AnnotationStub.CNaturalStruct -> TODO() - is AnnotationStub.CLength -> TODO() - is AnnotationStub.Deprecated -> TODO() - } - return KmAnnotation(classifier.fqNameSerialized, args) -} - /** - * @param shouldExpandTypeAliases describes how should we write type aliases. - * If [shouldExpandTypeAliases] is true then type alias-based types are written as - * ``` - * Type { - * abbreviatedType = AbbreviatedType.abbreviatedClassifier - * classifier = AbbreviatedType.underlyingType - * arguments = AbbreviatedType.underlyingType.typeArguments - * } - * ``` - * So we basically replacing type alias with underlying class. - * Otherwise: - * ``` - * Type { - * classifier = AbbreviatedType.abbreviatedClassifier - * } - * ``` - * As of 25 Nov 2019, the latter form is used only for KmTypeAlias.underlyingType. + * Collection of extension functions that simplify translation of + * StubIr elements to Kotlin Metadata. */ -// TODO: Add caching if needed. -private fun StubType.map(shouldExpandTypeAliases: Boolean = true): KmType = when (this) { - is AbbreviatedType -> { - val typeAliasClassifier = KmClassifier.TypeAlias(abbreviatedClassifier.fqNameSerialized) - if (shouldExpandTypeAliases) { - // Abbreviated and expanded types have the same nullability. - KmType(flags).also { km -> - km.abbreviatedType = KmType(flags).also { it.classifier = typeAliasClassifier } - val kmUnderlyingType = underlyingType.map(true) - km.arguments += kmUnderlyingType.arguments - km.classifier = kmUnderlyingType.classifier - } - } else { - KmType(flags).also { km -> km.classifier = typeAliasClassifier } - } - } - is ClassifierStubType -> KmType(flags).also { km -> - typeArguments.mapTo(km.arguments) { it.map(shouldExpandTypeAliases) } - km.classifier = KmClassifier.Class(classifier.fqNameSerialized) - } - is FunctionalType -> KmType(flags).also { km -> - typeArguments.mapTo(km.arguments) { it.map(shouldExpandTypeAliases) } - km.classifier = KmClassifier.Class(classifier.fqNameSerialized) - } - is TypeParameterType -> KmType(flags).also { km -> - km.classifier = KmClassifier.TypeParameter(id) - } -} +private class MappingExtensions( + private val typeParametersInterner: Interner +) { -private fun FunctionParameterStub.map(): KmValueParameter = - KmValueParameter(flags, name).also { km -> - val kmType = type.map() - if (isVararg) { - km.varargElementType = kmType + private fun flagsOfNotNull(vararg flags: Flag?): Flags = + flagsOf(*listOfNotNull(*flags).toTypedArray()) + + private fun mapOfNotNull(vararg entries: Pair?): Map = + listOfNotNull(*entries).toMap() + + private val VisibilityModifier.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC.takeIf { this == VisibilityModifier.PUBLIC }, + Flag.IS_PROTECTED.takeIf { this == VisibilityModifier.PROTECTED }, + Flag.IS_INTERNAL.takeIf { this == VisibilityModifier.INTERNAL }, + Flag.IS_PRIVATE.takeIf { this == VisibilityModifier.PRIVATE } + ) + + private val MemberStubModality.flags: Flags + get() = flagsOfNotNull( + Flag.IS_FINAL.takeIf { this == MemberStubModality.FINAL }, + Flag.IS_OPEN.takeIf { this == MemberStubModality.OPEN }, + Flag.IS_ABSTRACT.takeIf { this == MemberStubModality.ABSTRACT } + ) + + val FunctionStub.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC, + Flag.Function.IS_EXTERNAL, + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() } + ) or modality.flags + + val Classifier.fqNameSerialized: String + get() = buildString { + if (pkg.isNotEmpty()) { + append(pkg.replace('.', '/')) + append('/') + } + // Nested classes should dot-separated. + append(relativeFqName) + } + + val PropertyStub.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC, + Flag.Property.IS_DECLARATION, + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, + when (kind) { + is PropertyStub.Kind.Val -> null + is PropertyStub.Kind.Var -> Flag.Property.IS_VAR + is PropertyStub.Kind.Constant -> Flag.Property.IS_CONST + }, + when (kind) { + is PropertyStub.Kind.Constant -> null + is PropertyStub.Kind.Val, + is PropertyStub.Kind.Var -> Flag.Property.HAS_GETTER + }, + when (kind) { + is PropertyStub.Kind.Constant -> null + is PropertyStub.Kind.Val -> null + is PropertyStub.Kind.Var -> Flag.Property.HAS_SETTER + } + ) or modality.flags + + val PropertyStub.getterFlags: Flags + get() = when (kind) { + is PropertyStub.Kind.Val -> kind.getter.flags + is PropertyStub.Kind.Var -> kind.getter.flags + is PropertyStub.Kind.Constant -> flagsOf() + } + + private val PropertyAccessor.Getter.flags: Flags + get() = flagsOfNotNull( + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, + Flag.IS_PUBLIC, + Flag.IS_FINAL, + Flag.PropertyAccessor.IS_EXTERNAL.takeIf { this is PropertyAccessor.Getter.ExternalGetter } + ) + + val PropertyStub.setterFlags: Flags + get() = if (kind !is PropertyStub.Kind.Var) flagsOf() + else kind.setter.flags + + val PropertyAccessor.Setter.flags: Flags + get() = flagsOfNotNull( + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, + Flag.IS_PUBLIC, + Flag.IS_FINAL, + Flag.PropertyAccessor.IS_EXTERNAL.takeIf { this is PropertyAccessor.Setter.ExternalSetter } + ) + + val StubType.flags: Flags + get() = flagsOfNotNull( + Flag.Type.IS_NULLABLE.takeIf { nullable } + ) + + val TypealiasStub.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC + ) + + val FunctionParameterStub.flags: Flags + get() = flagsOfNotNull( + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() } + ) + + fun AnnotationStub.map(): KmAnnotation { + fun Pair.asAnnotationArgument() = + (first to KmAnnotationArgument.StringValue(second)).takeIf { second.isNotEmpty() } + + fun replaceWith(replaceWith: String) = KmAnnotationArgument.AnnotationValue(KmAnnotation( + Classifier.topLevel("kotlin", "ReplaceWith").fqNameSerialized, + mapOfNotNull( + "imports" to KmAnnotationArgument.ArrayValue(emptyList()), + ("expression" to replaceWith).asAnnotationArgument() + ) + )) + + fun deprecationLevel(level: DeprecationLevel) = KmAnnotationArgument.EnumValue( + Classifier.topLevel("kotlin", "DeprecationLevel").fqNameSerialized, + level.name + ) + + val args = when (this) { + AnnotationStub.ObjC.ConsumesReceiver -> emptyMap() + AnnotationStub.ObjC.ReturnsRetained -> emptyMap() + is AnnotationStub.ObjC.Method -> mapOfNotNull( + ("selector" to selector).asAnnotationArgument(), + ("encoding" to encoding).asAnnotationArgument(), + ("isStret" to KmAnnotationArgument.BooleanValue(isStret)) + ) + is AnnotationStub.ObjC.Factory -> mapOfNotNull( + ("selector" to selector).asAnnotationArgument(), + ("encoding" to encoding).asAnnotationArgument(), + ("isStret" to KmAnnotationArgument.BooleanValue(isStret)) + ) + AnnotationStub.ObjC.Consumed -> emptyMap() + is AnnotationStub.ObjC.Constructor -> mapOfNotNull( + ("designated" to KmAnnotationArgument.BooleanValue(designated)), + ("initSelector" to selector).asAnnotationArgument() + ) + is AnnotationStub.ObjC.ExternalClass -> mapOfNotNull( + ("protocolGetter" to protocolGetter).asAnnotationArgument(), + ("binaryName" to binaryName).asAnnotationArgument() + ) + AnnotationStub.CCall.CString -> emptyMap() + AnnotationStub.CCall.WCString -> emptyMap() + is AnnotationStub.CCall.Symbol -> mapOfNotNull( + ("id" to symbolName).asAnnotationArgument() + ) + is AnnotationStub.CStruct -> mapOfNotNull( + ("spelling" to struct).asAnnotationArgument() + ) + is AnnotationStub.CNaturalStruct -> + error("@CNaturalStruct should not be used for Kotlin/Native interop") + is AnnotationStub.CLength -> mapOfNotNull( + "value" to KmAnnotationArgument.LongValue(length) + ) + is AnnotationStub.Deprecated -> mapOfNotNull( + ("message" to message).asAnnotationArgument(), + ("replaceWith" to replaceWith(replaceWith)), + ("level" to deprecationLevel(DeprecationLevel.ERROR)) + ) + } + return KmAnnotation(classifier.fqNameSerialized, args) + } + + /** + * @param shouldExpandTypeAliases describes how should we write type aliases. + * If [shouldExpandTypeAliases] is true then type alias-based types are written as + * ``` + * Type { + * abbreviatedType = AbbreviatedType.abbreviatedClassifier + * classifier = AbbreviatedType.underlyingType + * arguments = AbbreviatedType.underlyingType.typeArguments + * } + * ``` + * So we basically replacing type alias with underlying class. + * Otherwise: + * ``` + * Type { + * classifier = AbbreviatedType.abbreviatedClassifier + * } + * ``` + * As of 25 Nov 2019, the latter form is used only for KmTypeAlias.underlyingType. + */ + // TODO: Add caching if needed. + fun StubType.map(shouldExpandTypeAliases: Boolean = true): KmType = when (this) { + is AbbreviatedType -> { + val typeAliasClassifier = KmClassifier.TypeAlias(abbreviatedClassifier.fqNameSerialized) + if (shouldExpandTypeAliases) { + // Abbreviated and expanded types have the same nullability. + KmType(flags).also { km -> + km.abbreviatedType = KmType(flags).also { it.classifier = typeAliasClassifier } + val kmUnderlyingType = underlyingType.map(true) + km.arguments += kmUnderlyingType.arguments + km.classifier = kmUnderlyingType.classifier + } } else { - km.type = kmType + KmType(flags).also { km -> km.classifier = typeAliasClassifier } } - annotations.mapTo(km.annotations, AnnotationStub::map) } - -private fun TypeParameterStub.map(): KmTypeParameter = - KmTypeParameter(flagsOf(), name, id, KmVariance.INVARIANT).also { km -> - km.upperBounds.addIfNotNull(upperBound?.map()) + is ClassifierStubType -> KmType(flags).also { km -> + typeArguments.mapTo(km.arguments) { it.map(shouldExpandTypeAliases) } + km.classifier = KmClassifier.Class(classifier.fqNameSerialized) } - -private fun TypeArgument.map(expanded: Boolean=true): KmTypeProjection = when (this) { - TypeArgument.StarProjection -> KmTypeProjection.STAR - is TypeArgumentStub -> KmTypeProjection(variance.map(), type.map(expanded)) - else -> error("Unexpected TypeArgument: $this") -} - -private fun TypeArgument.Variance.map(): KmVariance = when (this) { - TypeArgument.Variance.INVARIANT -> KmVariance.INVARIANT - TypeArgument.Variance.IN -> KmVariance.IN - TypeArgument.Variance.OUT -> KmVariance.OUT -} - -private fun ConstantStub.mapToAnnotationArgument(): KmAnnotationArgument<*> = when (this) { - is StringConstantStub -> KmAnnotationArgument.StringValue(value) - is IntegralConstantStub -> when (size) { - 1 -> if (isSigned) { - KmAnnotationArgument.ByteValue(value.toByte()) - } else { - KmAnnotationArgument.UByteValue(value.toByte()) + is FunctionalType -> KmType(flags).also { km -> + typeArguments.mapTo(km.arguments) { it.map(shouldExpandTypeAliases) } + km.classifier = KmClassifier.Class(classifier.fqNameSerialized) } - 2 -> if (isSigned) { - KmAnnotationArgument.ShortValue(value.toShort()) - } else { - KmAnnotationArgument.UShortValue(value.toShort()) + is TypeParameterType -> KmType(flags).also { km -> + km.classifier = KmClassifier.TypeParameter(id) } - 4 -> if (isSigned) { - KmAnnotationArgument.IntValue(value.toInt()) - } else { - KmAnnotationArgument.UIntValue(value.toInt()) - } - 8 -> if (isSigned) { - KmAnnotationArgument.LongValue(value) - } else { - KmAnnotationArgument.ULongValue(value) - } - - else -> error("Integral constant of value $value with unexpected size of $size.") } - is DoubleConstantStub -> when (size) { - 4 -> KmAnnotationArgument.FloatValue(value.toFloat()) - 8 -> KmAnnotationArgument.DoubleValue(value) - else -> error("Floating-point constant of value $value with unexpected size of $size.") + + fun FunctionParameterStub.map(): KmValueParameter = + KmValueParameter(flags, name).also { km -> + val kmType = type.map() + if (isVararg) { + km.varargElementType = kmType + } else { + km.type = kmType + } + annotations.mapTo(km.annotations, { it.map() }) + } + + fun TypeParameterStub.map(): KmTypeParameter = + KmTypeParameter(flagsOf(), name, id, KmVariance.INVARIANT).also { km -> + km.upperBounds.addIfNotNull(upperBound?.map()) + } + + private fun TypeArgument.map(expanded: Boolean = true): KmTypeProjection = when (this) { + TypeArgument.StarProjection -> KmTypeProjection.STAR + is TypeArgumentStub -> KmTypeProjection(variance.map(), type.map(expanded)) + else -> error("Unexpected TypeArgument: $this") } -} -private val TypeParameterType.id: Int - get() = TODO() + private fun TypeArgument.Variance.map(): KmVariance = when (this) { + TypeArgument.Variance.INVARIANT -> KmVariance.INVARIANT + TypeArgument.Variance.IN -> KmVariance.IN + TypeArgument.Variance.OUT -> KmVariance.OUT + } -private val TypeParameterStub.id: Int - get() = TODO() \ No newline at end of file + fun ConstantStub.mapToAnnotationArgument(): KmAnnotationArgument<*> = when (this) { + is StringConstantStub -> KmAnnotationArgument.StringValue(value) + is IntegralConstantStub -> when (size) { + 1 -> if (isSigned) { + KmAnnotationArgument.ByteValue(value.toByte()) + } else { + KmAnnotationArgument.UByteValue(value.toByte()) + } + 2 -> if (isSigned) { + KmAnnotationArgument.ShortValue(value.toShort()) + } else { + KmAnnotationArgument.UShortValue(value.toShort()) + } + 4 -> if (isSigned) { + KmAnnotationArgument.IntValue(value.toInt()) + } else { + KmAnnotationArgument.UIntValue(value.toInt()) + } + 8 -> if (isSigned) { + KmAnnotationArgument.LongValue(value) + } else { + KmAnnotationArgument.ULongValue(value) + } + + else -> error("Integral constant of value $value with unexpected size of $size.") + } + is DoubleConstantStub -> when (size) { + 4 -> KmAnnotationArgument.FloatValue(value.toFloat()) + 8 -> KmAnnotationArgument.DoubleValue(value) + else -> error("Floating-point constant of value $value with unexpected size of $size.") + } + } + + private val TypeParameterType.id: Int + get() = typeParameterDeclaration.id + + private val TypeParameterStub.id: Int + get() = typeParametersInterner.intern(this) +} \ No newline at end of file diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt index 23c38706d01..7034af5f99d 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt @@ -65,7 +65,8 @@ class FunctionalType( class TypeParameterType( val name: String, - override val nullable: Boolean + override val nullable: Boolean, + val typeParameterDeclaration: TypeParameterStub ) : StubType() { override val typeArguments: List = emptyList() }