From d7a3310042e85b5ebd60ca77603c2cb3ffaacbe5 Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Mon, 24 May 2021 18:00:51 +0300 Subject: [PATCH] [K/N] KT-43780: support of more convenient objects using from objC/Swift --- .../objcexport/ObjCExportCodeGenerator.kt | 4 +- .../konan/objcexport/ObjCExportCodeSpec.kt | 11 ++- .../objcexport/ObjCExportHeaderGenerator.kt | 37 ++++++-- .../konan/objcexport/ObjCExportNamer.kt | 17 +++- .../tests/objcexport/expectedLazy.h | 88 +++++++++++++++++++ .../tests/objcexport/expectedLazyNoGenerics.h | 88 +++++++++++++++++++ .../tests/objcexport/kt43780.kt | 36 ++++++++ .../tests/objcexport/kt43780.swift | 48 ++++++++++ 8 files changed, 318 insertions(+), 11 deletions(-) create mode 100644 kotlin-native/backend.native/tests/objcexport/kt43780.kt create mode 100644 kotlin-native/backend.native/tests/objcexport/kt43780.swift diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 12d02d4e8e3..dd3e4d61868 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -1298,10 +1298,10 @@ private fun ObjCExportCodeGenerator.createTypeAdapter( classAdapters += createEnumValuesAdapter(it.valuesFunctionSymbol.owner, it.selector) } is ObjCGetterForObjectInstance -> { - classAdapters += if (irClass.isUnit()) { + classAdapters += if (it.classSymbol.owner.isUnit()) { createUnitInstanceAdapter(it.selector) } else { - createObjectInstanceAdapter(irClass, it.selector) + createObjectInstanceAdapter(it.classSymbol.owner, it.selector) } } ObjCKotlinThrowableAsErrorMethod -> { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportCodeSpec.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportCodeSpec.kt index f10ed75390d..f6e2bfe6e35 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportCodeSpec.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportCodeSpec.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny +import org.jetbrains.kotlin.resolve.descriptorUtil.hasCompanionObject internal fun ObjCExportedInterface.createCodeSpec(symbolTable: SymbolTable): ObjCExportCodeSpec { @@ -73,7 +74,13 @@ internal fun ObjCExportedInterface.createCodeSpec(symbolTable: SymbolTable): Obj } if (descriptor.kind == ClassKind.OBJECT) { - methods += ObjCGetterForObjectInstance(namer.getObjectInstanceSelector(descriptor)) + methods += ObjCGetterForObjectInstance(namer.getObjectInstanceSelector(descriptor), irClassSymbol) + methods += ObjCGetterForObjectInstance(namer.getObjectPropertySelector(descriptor), irClassSymbol) + } + + if (descriptor.needCompanionObjectProperty(namer)) { + methods += ObjCGetterForObjectInstance(namer.getCompanionObjectPropertySelector(descriptor), + symbolTable.referenceClass(descriptor.companionObjectDescriptor!!)) } if (descriptor.kind == ClassKind.ENUM_CLASS) { @@ -152,7 +159,7 @@ internal class ObjCClassMethodForKotlinEnumValues( val selector: String ) : ObjCMethodSpec() -internal class ObjCGetterForObjectInstance(val selector: String) : ObjCMethodSpec() +internal class ObjCGetterForObjectInstance(val selector: String, val classSymbol: IrClassSymbol) : ObjCMethodSpec() internal object ObjCKotlinThrowableAsErrorMethod : ObjCMethodSpec() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt index 5bdff481b25..12022bfa701 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt @@ -352,14 +352,35 @@ internal class ObjCExportTranslatorImpl( } } + if (descriptor.needCompanionObjectProperty(namer)) { + add { + ObjCProperty( + ObjCExportNamer.companionObjectPropertyName, null, + mapReferenceType(descriptor.companionObjectDescriptor!!.defaultType, genericExportScope), + listOf("class", "readonly"), + getterName = namer.getCompanionObjectPropertySelector(descriptor), + declarationAttributes = listOf(swiftNameAttribute(ObjCExportNamer.companionObjectPropertyName)) + ) + } + } // TODO: consider adding exception-throwing impls for these. when (descriptor.kind) { - ClassKind.OBJECT -> add { - ObjCMethod( - null, false, ObjCInstanceType, - listOf(namer.getObjectInstanceSelector(descriptor)), emptyList(), - listOf(swiftNameAttribute("init()")) - ) + ClassKind.OBJECT -> { + add { + ObjCMethod( + null, false, ObjCInstanceType, + listOf(namer.getObjectInstanceSelector(descriptor)), emptyList(), + listOf(swiftNameAttribute("init()")) + ) + } + add { + ObjCProperty( + ObjCExportNamer.objectPropertyName, null, + mapReferenceType(descriptor.defaultType, genericExportScope), listOf("class", "readonly"), + getterName = namer.getObjectPropertySelector(descriptor), + declarationAttributes = listOf(swiftNameAttribute(ObjCExportNamer.objectPropertyName)) + ) + } } ClassKind.ENUM_CLASS -> { val type = mapType(descriptor.defaultType, ReferenceBridge, ObjCNoneExportScope) @@ -1292,6 +1313,10 @@ private fun computeSuperClassType(descriptor: ClassDescriptor): KotlinType? = de internal const val OBJC_SUBCLASSING_RESTRICTED = "objc_subclassing_restricted" +internal fun ClassDescriptor.needCompanionObjectProperty(namer: ObjCExportNamer) = hasCompanionObject && + (kind != ClassKind.ENUM_CLASS || enumEntries.all { namer.getEnumEntrySelector(it) != ObjCExportNamer.companionObjectPropertyName }) + + private fun Deprecation.toDeprecationAttribute(): String { val attribute = when (deprecationLevel) { DeprecationLevelValue.WARNING -> "deprecated" diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt index e2de7759860..fe20e192a6e 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt @@ -67,8 +67,13 @@ interface ObjCExportNamer { val mutableMapName: ClassOrProtocolName val kotlinNumberName: ClassOrProtocolName + fun getObjectPropertySelector(descriptor: ClassDescriptor): String + fun getCompanionObjectPropertySelector(descriptor: ClassDescriptor): String + companion object { - internal val kotlinThrowableAsErrorMethodName: String = "asError" + internal const val kotlinThrowableAsErrorMethodName: String = "asError" + internal const val objectPropertyName: String = "shared" + internal const val companionObjectPropertyName: String = "companion" } } @@ -600,6 +605,16 @@ internal class ObjCExportNamerImpl( } } + + override fun getObjectPropertySelector(descriptor: ClassDescriptor): String { + val collides = ObjCExportNamer.objectPropertyName == getObjectInstanceSelector(descriptor) + return ObjCExportNamer.objectPropertyName + (if (collides) "_" else "") + } + + override fun getCompanionObjectPropertySelector(descriptor: ClassDescriptor): String { + return ObjCExportNamer.companionObjectPropertyName + } + init { if (!local) { forceAssignPredefined(builtIns) diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h index 9f28582e86a..dd16057b10f 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h @@ -731,6 +731,86 @@ __attribute__((swift_name("Kt43599Kt"))) @property (class, readonly) NSString *topLevelLateinitProperty __attribute__((swift_name("topLevelLateinitProperty"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780TestObject"))) +@interface KtKT43780TestObject : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)kT43780TestObject __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtKT43780TestObject *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t x __attribute__((swift_name("x"))); +@property (readonly) int32_t y __attribute__((swift_name("y"))); +@property (readonly) NSString *shared __attribute__((swift_name("shared"))); +@property (readonly) NSString *Shared __attribute__((swift_name("Shared"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780TestClassWithCompanion"))) +@interface KtKT43780TestClassWithCompanion : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (class, readonly, getter=companion) KtKT43780TestClassWithCompanionCompanion *companion __attribute__((swift_name("companion"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780TestClassWithCompanion.Companion"))) +@interface KtKT43780TestClassWithCompanionCompanion : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtKT43780TestClassWithCompanionCompanion *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t z __attribute__((swift_name("z"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Shared"))) +@interface KtShared : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)shared __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared_) KtShared *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t x __attribute__((swift_name("x"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Companion"))) +@interface KtCompanion : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (class, readonly, getter=companion) KtCompanionCompanion *companion __attribute__((swift_name("companion"))); +@property (readonly) int32_t t __attribute__((swift_name("t"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Companion.Companion"))) +@interface KtCompanionCompanion : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtCompanionCompanion *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t x __attribute__((swift_name("x"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780Enum"))) +@interface KtKT43780Enum : KtKotlinEnum ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@property (class, readonly) KtKT43780Enum *companion __attribute__((swift_name("companion"))); ++ (KtKotlinArray *)values __attribute__((swift_name("values()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780Enum.Companion"))) +@interface KtKT43780EnumCompanion : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtKT43780EnumCompanion *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t x __attribute__((swift_name("x"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("LibraryKt"))) @interface KtLibraryKt : KtBase @@ -1020,6 +1100,7 @@ __attribute__((swift_name("WithCompanionAndObject"))) @interface KtWithCompanionAndObject : KtBase - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (class, readonly, getter=companion) KtWithCompanionAndObjectCompanion *companion __attribute__((swift_name("companion"))); @end; __attribute__((objc_subclassing_restricted)) @@ -1028,6 +1109,7 @@ __attribute__((swift_name("WithCompanionAndObject.Companion"))) + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); + (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtWithCompanionAndObjectCompanion *shared __attribute__((swift_name("shared"))); @property (readonly) NSString *str __attribute__((swift_name("str"))); @property id _Nullable named __attribute__((swift_name("named"))); @end; @@ -1040,6 +1122,7 @@ __attribute__((swift_name("WithCompanionAndObject.Named"))) - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); + (instancetype)new __attribute__((unavailable)); + (instancetype)named __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtWithCompanionAndObjectNamed *shared __attribute__((swift_name("shared"))); - (NSString *)iFun __attribute__((swift_name("iFun()"))); @end; @@ -1565,6 +1648,7 @@ __attribute__((swift_name("IntBlocksImpl"))) + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); + (instancetype)intBlocksImpl __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtIntBlocksImpl *shared __attribute__((swift_name("shared"))); - (KtInt *(^)(KtInt *))getPlusOneBlock __attribute__((swift_name("getPlusOneBlock()"))); - (int32_t)callBlockArgument:(int32_t)argument block:(KtInt *(^)(KtInt *))block __attribute__((swift_name("callBlock(argument:block:)"))); @end; @@ -1582,6 +1666,7 @@ __attribute__((swift_name("UnitBlockCoercionImpl"))) + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); + (instancetype)unitBlockCoercionImpl __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtUnitBlockCoercionImpl *shared __attribute__((swift_name("shared"))); - (KtKotlinUnit *(^)(void))coerceBlock:(void (^)(void))block __attribute__((swift_name("coerce(block:)"))); - (void (^)(void))uncoerceBlock:(KtKotlinUnit *(^)(void))block __attribute__((swift_name("uncoerce(block:)"))); @end; @@ -1662,6 +1747,7 @@ __attribute__((swift_name("TestInvalidIdentifiers"))) @interface KtTestInvalidIdentifiers : KtBase - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (class, readonly, getter=companion) KtTestInvalidIdentifiersCompanion_ *companion __attribute__((swift_name("companion"))); - (int32_t)a_d_d_1:(int32_t)_1 _2:(int32_t)_2 _3:(int32_t)_3 __attribute__((swift_name("a_d_d(_1:_2:_3:)"))); @property NSString *_status __attribute__((swift_name("_status"))); @property (readonly) unichar __ __attribute__((swift_name("__"))); @@ -1702,6 +1788,7 @@ __attribute__((swift_name("TestInvalidIdentifiers.Companion_"))) + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); + (instancetype)companion_ __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtTestInvalidIdentifiersCompanion_ *shared __attribute__((swift_name("shared"))); @property (readonly) int32_t _42 __attribute__((swift_name("_42"))); @end; @@ -2097,6 +2184,7 @@ __attribute__((swift_name("GH3525"))) - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); + (instancetype)new __attribute__((unavailable)); + (instancetype)gH3525 __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtGH3525 *shared __attribute__((swift_name("shared"))); @end; __attribute__((objc_subclassing_restricted)) diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h index 253c436bf46..af91b0fbc1d 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h @@ -673,6 +673,86 @@ __attribute__((swift_name("Kt43599Kt"))) @property (class, readonly) NSString *topLevelLateinitProperty __attribute__((swift_name("topLevelLateinitProperty"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780TestObject"))) +@interface KtKT43780TestObject : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)kT43780TestObject __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtKT43780TestObject *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t x __attribute__((swift_name("x"))); +@property (readonly) int32_t y __attribute__((swift_name("y"))); +@property (readonly) NSString *shared __attribute__((swift_name("shared"))); +@property (readonly) NSString *Shared __attribute__((swift_name("Shared"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780TestClassWithCompanion"))) +@interface KtKT43780TestClassWithCompanion : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (class, readonly, getter=companion) KtKT43780TestClassWithCompanionCompanion *companion __attribute__((swift_name("companion"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780TestClassWithCompanion.Companion"))) +@interface KtKT43780TestClassWithCompanionCompanion : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtKT43780TestClassWithCompanionCompanion *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t z __attribute__((swift_name("z"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Shared"))) +@interface KtShared : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)shared __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared_) KtShared *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t x __attribute__((swift_name("x"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Companion"))) +@interface KtCompanion : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (class, readonly, getter=companion) KtCompanionCompanion *companion __attribute__((swift_name("companion"))); +@property (readonly) int32_t t __attribute__((swift_name("t"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Companion.Companion"))) +@interface KtCompanionCompanion : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtCompanionCompanion *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t x __attribute__((swift_name("x"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780Enum"))) +@interface KtKT43780Enum : KtKotlinEnum ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@property (class, readonly) KtKT43780Enum *companion __attribute__((swift_name("companion"))); ++ (KtKotlinArray *)values __attribute__((swift_name("values()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT43780Enum.Companion"))) +@interface KtKT43780EnumCompanion : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtKT43780EnumCompanion *shared __attribute__((swift_name("shared"))); +@property (readonly) int32_t x __attribute__((swift_name("x"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("LibraryKt"))) @interface KtLibraryKt : KtBase @@ -962,6 +1042,7 @@ __attribute__((swift_name("WithCompanionAndObject"))) @interface KtWithCompanionAndObject : KtBase - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (class, readonly, getter=companion) KtWithCompanionAndObjectCompanion *companion __attribute__((swift_name("companion"))); @end; __attribute__((objc_subclassing_restricted)) @@ -970,6 +1051,7 @@ __attribute__((swift_name("WithCompanionAndObject.Companion"))) + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); + (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtWithCompanionAndObjectCompanion *shared __attribute__((swift_name("shared"))); @property (readonly) NSString *str __attribute__((swift_name("str"))); @property id _Nullable named __attribute__((swift_name("named"))); @end; @@ -982,6 +1064,7 @@ __attribute__((swift_name("WithCompanionAndObject.Named"))) - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); + (instancetype)new __attribute__((unavailable)); + (instancetype)named __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtWithCompanionAndObjectNamed *shared __attribute__((swift_name("shared"))); - (NSString *)iFun __attribute__((swift_name("iFun()"))); @end; @@ -1507,6 +1590,7 @@ __attribute__((swift_name("IntBlocksImpl"))) + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); + (instancetype)intBlocksImpl __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtIntBlocksImpl *shared __attribute__((swift_name("shared"))); - (KtInt *(^)(KtInt *))getPlusOneBlock __attribute__((swift_name("getPlusOneBlock()"))); - (int32_t)callBlockArgument:(int32_t)argument block:(KtInt *(^)(KtInt *))block __attribute__((swift_name("callBlock(argument:block:)"))); @end; @@ -1524,6 +1608,7 @@ __attribute__((swift_name("UnitBlockCoercionImpl"))) + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); + (instancetype)unitBlockCoercionImpl __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtUnitBlockCoercionImpl *shared __attribute__((swift_name("shared"))); - (KtKotlinUnit *(^)(void))coerceBlock:(void (^)(void))block __attribute__((swift_name("coerce(block:)"))); - (void (^)(void))uncoerceBlock:(KtKotlinUnit *(^)(void))block __attribute__((swift_name("uncoerce(block:)"))); @end; @@ -1604,6 +1689,7 @@ __attribute__((swift_name("TestInvalidIdentifiers"))) @interface KtTestInvalidIdentifiers : KtBase - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (class, readonly, getter=companion) KtTestInvalidIdentifiersCompanion_ *companion __attribute__((swift_name("companion"))); - (int32_t)a_d_d_1:(int32_t)_1 _2:(int32_t)_2 _3:(int32_t)_3 __attribute__((swift_name("a_d_d(_1:_2:_3:)"))); @property NSString *_status __attribute__((swift_name("_status"))); @property (readonly) unichar __ __attribute__((swift_name("__"))); @@ -1644,6 +1730,7 @@ __attribute__((swift_name("TestInvalidIdentifiers.Companion_"))) + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); + (instancetype)companion_ __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtTestInvalidIdentifiersCompanion_ *shared __attribute__((swift_name("shared"))); @property (readonly) int32_t _42 __attribute__((swift_name("_42"))); @end; @@ -2039,6 +2126,7 @@ __attribute__((swift_name("GH3525"))) - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); + (instancetype)new __attribute__((unavailable)); + (instancetype)gH3525 __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) KtGH3525 *shared __attribute__((swift_name("shared"))); @end; __attribute__((objc_subclassing_restricted)) diff --git a/kotlin-native/backend.native/tests/objcexport/kt43780.kt b/kotlin-native/backend.native/tests/objcexport/kt43780.kt new file mode 100644 index 00000000000..d82bb8b65e9 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt43780.kt @@ -0,0 +1,36 @@ +/* + * 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. + */ + +object KT43780TestObject { + val x = 5 + val y = 6 + val shared = "shared" + val Shared = "Shared" +} + +class KT43780TestClassWithCompanion { + companion object { + val z = 7 + } +} + +object Shared { + val x = 8 +} + +class Companion { + val t = 10 + companion object { + val x = 9 + } +} + +enum class KT43780Enum { + COMPANION; + + companion object { + val x = 11 + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/kt43780.swift b/kotlin-native/backend.native/tests/objcexport/kt43780.swift new file mode 100644 index 00000000000..a1a6bf565a7 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt43780.swift @@ -0,0 +1,48 @@ +import Kt + +private func testObject() throws { + let object = KT43780TestObject.shared + try assertEquals(actual: object.x, expected: 5) + try assertEquals(actual: object.y, expected: 6) + try assertEquals(actual: object.shared, expected: "shared") + try assertEquals(actual: object.Shared, expected: "Shared") + try assertTrue(object === KT43780TestObject()) +} + +private func testCompanionObject() throws { + let object = KT43780TestClassWithCompanion.companion + try assertEquals(actual: object.z, expected: 7) + try assertTrue(object === KT43780TestClassWithCompanion.Companion()) + try assertTrue(object === KT43780TestClassWithCompanion.Companion.shared) +} + +private func testNameClash() throws { + let object = Shared.shared + try assertEquals(actual: object.x, expected: 8) + try assertTrue(object === Shared()) + let object2 = Companion.companion + try assertEquals(actual: object2.x, expected: 9) + try assertTrue(object2 === Companion.Companion()) + let object3 = Companion() + try assertEquals(actual: object3.t, expected: 10) + let object4 = Companion() + try assertEquals(actual: object4.t, expected: 10) + try assertTrue(object3 !== object4) + + let object5 = KT43780Enum.Companion() + try assertEquals(actual: object5.x, expected: 11) + try assertTrue(object5 === KT43780Enum.Companion()) + let enumEntry : KT43780Enum = KT43780Enum.companion + try assertEquals(actual: enumEntry.name, expected: "COMPANION") +} + + +class Kt43780Tests : SimpleTestProvider { + override init() { + super.init() + + test("testObject", testObject) + test("testCompanionObject", testCompanionObject) + test("testNameClash", testNameClash) + } +}