From c7b100a41a5cbca55563c579541247224b234912 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Tue, 25 Apr 2023 18:18:50 +0300 Subject: [PATCH] [K/N] KT-56464: backend tests --- .../tests/objcexport/expectedLazy.h | 88 +++++++++++++ .../expectedLazyLegacySuspendUnit.h | 88 +++++++++++++ .../tests/objcexport/expectedLazyNoGenerics.h | 88 +++++++++++++ .../tests/objcexport/hiddenfromobjc.kt | 123 ++++++++++++++++++ .../tests/objcexport/hiddenfromobjc.swift | 58 +++++++++ 5 files changed, 445 insertions(+) create mode 100644 kotlin-native/backend.native/tests/objcexport/hiddenfromobjc.kt create mode 100644 kotlin-native/backend.native/tests/objcexport/hiddenfromobjc.swift diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h index ebd0de1db99..fc2bcfba02c 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h @@ -685,6 +685,94 @@ __attribute__((swift_name("TestGH3992.B"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ClassNotAvailableInSwift"))) +@interface KtClassNotAvailableInSwift : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass"))) +@interface KtParentClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.NestedClass"))) +@interface KtParentClassNestedClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.NestedClassDeeplyNestedClass"))) +@interface KtParentClassNestedClassDeeplyNestedClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.InnerClass"))) +@interface KtParentClassInnerClass : NSObject +@end + +__attribute__((swift_name("InterfaceNotAvailableInSwift"))) +@protocol KtInterfaceNotAvailableInSwift +@required +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("UnavailableEnum"))) +@interface KtUnavailableEnum : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("UnavailableObject"))) +@interface KtUnavailableObject : NSObject +@end + +__attribute__((swift_name("SealedClass"))) +@interface KtSealedClass : KtBase +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.A"))) +@interface KtSealedClassA : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.B"))) +@interface KtSealedClassB : KtSealedClass +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.C"))) +@interface KtSealedClassC : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("WrapperOverUnavailable"))) +@interface KtWrapperOverUnavailable : KtBase +- (instancetype)initWithArg:(T)arg __attribute__((swift_name("init(arg:)"))) __attribute__((objc_designated_initializer)); +@property (readonly) T arg __attribute__((swift_name("arg"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("HiddenfromobjcKt"))) +@interface KtHiddenfromobjcKt : KtBase ++ (id)useOfUnavailableClassParam:(id)param __attribute__((swift_name("useOfUnavailableClass(param:)"))); ++ (id _Nullable)useOfNullableUnavailableClassParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableClass(param:)"))); ++ (id)produceUnavailable __attribute__((swift_name("produceUnavailable()"))); ++ (NSString *)consumeUnavailableParam:(id)param __attribute__((swift_name("consumeUnavailable(param:)"))); ++ (id)createUnavailableInterface __attribute__((swift_name("createUnavailableInterface()"))); ++ (NSString * _Nullable)useOfNullableUnavailableInterfaceParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableInterface(param:)"))); ++ (id)createUnavailableEnum __attribute__((swift_name("createUnavailableEnum()"))); ++ (NSString *)useOfUnavailableEnumParam:(id)param __attribute__((swift_name("useOfUnavailableEnum(param:)"))); ++ (NSString *)useOfNullableUnavailableEnumParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableEnum(param:)"))); ++ (id)getUnavailableObject __attribute__((swift_name("getUnavailableObject()"))); ++ (NSString *)useOfUnavailableObjectParam:(id)param __attribute__((swift_name("useOfUnavailableObject(param:)"))); ++ (NSString * _Nullable)useOfNullableUnavailableObjectParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableObject(param:)"))); ++ (KtSealedClass *)createSealedClass __attribute__((swift_name("createSealedClass()"))); ++ (NSString *)useSealedClassParam:(KtSealedClass *)param __attribute__((swift_name("useSealedClass(param:)"))); ++ (NSString *)useUnavailableA:(id)a __attribute__((swift_name("useUnavailable(a:)"))); +@end + __attribute__((swift_name("InterfaceNameManglingI1"))) @protocol KtInterfaceNameManglingI1 @required diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h index 093460d9588..f061c52d37d 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h @@ -685,6 +685,94 @@ __attribute__((swift_name("TestGH3992.B"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ClassNotAvailableInSwift"))) +@interface KtClassNotAvailableInSwift : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass"))) +@interface KtParentClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.NestedClass"))) +@interface KtParentClassNestedClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.NestedClassDeeplyNestedClass"))) +@interface KtParentClassNestedClassDeeplyNestedClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.InnerClass"))) +@interface KtParentClassInnerClass : NSObject +@end + +__attribute__((swift_name("InterfaceNotAvailableInSwift"))) +@protocol KtInterfaceNotAvailableInSwift +@required +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("UnavailableEnum"))) +@interface KtUnavailableEnum : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("UnavailableObject"))) +@interface KtUnavailableObject : NSObject +@end + +__attribute__((swift_name("SealedClass"))) +@interface KtSealedClass : KtBase +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.A"))) +@interface KtSealedClassA : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.B"))) +@interface KtSealedClassB : KtSealedClass +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.C"))) +@interface KtSealedClassC : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("WrapperOverUnavailable"))) +@interface KtWrapperOverUnavailable : KtBase +- (instancetype)initWithArg:(T)arg __attribute__((swift_name("init(arg:)"))) __attribute__((objc_designated_initializer)); +@property (readonly) T arg __attribute__((swift_name("arg"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("HiddenfromobjcKt"))) +@interface KtHiddenfromobjcKt : KtBase ++ (id)useOfUnavailableClassParam:(id)param __attribute__((swift_name("useOfUnavailableClass(param:)"))); ++ (id _Nullable)useOfNullableUnavailableClassParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableClass(param:)"))); ++ (id)produceUnavailable __attribute__((swift_name("produceUnavailable()"))); ++ (NSString *)consumeUnavailableParam:(id)param __attribute__((swift_name("consumeUnavailable(param:)"))); ++ (id)createUnavailableInterface __attribute__((swift_name("createUnavailableInterface()"))); ++ (NSString * _Nullable)useOfNullableUnavailableInterfaceParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableInterface(param:)"))); ++ (id)createUnavailableEnum __attribute__((swift_name("createUnavailableEnum()"))); ++ (NSString *)useOfUnavailableEnumParam:(id)param __attribute__((swift_name("useOfUnavailableEnum(param:)"))); ++ (NSString *)useOfNullableUnavailableEnumParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableEnum(param:)"))); ++ (id)getUnavailableObject __attribute__((swift_name("getUnavailableObject()"))); ++ (NSString *)useOfUnavailableObjectParam:(id)param __attribute__((swift_name("useOfUnavailableObject(param:)"))); ++ (NSString * _Nullable)useOfNullableUnavailableObjectParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableObject(param:)"))); ++ (KtSealedClass *)createSealedClass __attribute__((swift_name("createSealedClass()"))); ++ (NSString *)useSealedClassParam:(KtSealedClass *)param __attribute__((swift_name("useSealedClass(param:)"))); ++ (NSString *)useUnavailableA:(id)a __attribute__((swift_name("useUnavailable(a:)"))); +@end + __attribute__((swift_name("InterfaceNameManglingI1"))) @protocol KtInterfaceNameManglingI1 @required diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h index 302aba0a790..0fc1c66ac87 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h @@ -685,6 +685,94 @@ __attribute__((swift_name("TestGH3992.B"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ClassNotAvailableInSwift"))) +@interface KtClassNotAvailableInSwift : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass"))) +@interface KtParentClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.NestedClass"))) +@interface KtParentClassNestedClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.NestedClassDeeplyNestedClass"))) +@interface KtParentClassNestedClassDeeplyNestedClass : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ParentClass.InnerClass"))) +@interface KtParentClassInnerClass : NSObject +@end + +__attribute__((swift_name("InterfaceNotAvailableInSwift"))) +@protocol KtInterfaceNotAvailableInSwift +@required +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("UnavailableEnum"))) +@interface KtUnavailableEnum : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("UnavailableObject"))) +@interface KtUnavailableObject : NSObject +@end + +__attribute__((swift_name("SealedClass"))) +@interface KtSealedClass : KtBase +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.A"))) +@interface KtSealedClassA : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.B"))) +@interface KtSealedClassB : KtSealedClass +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SealedClass.C"))) +@interface KtSealedClassC : NSObject +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("WrapperOverUnavailable"))) +@interface KtWrapperOverUnavailable : KtBase +- (instancetype)initWithArg:(id)arg __attribute__((swift_name("init(arg:)"))) __attribute__((objc_designated_initializer)); +@property (readonly) id arg __attribute__((swift_name("arg"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("HiddenfromobjcKt"))) +@interface KtHiddenfromobjcKt : KtBase ++ (id)useOfUnavailableClassParam:(id)param __attribute__((swift_name("useOfUnavailableClass(param:)"))); ++ (id _Nullable)useOfNullableUnavailableClassParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableClass(param:)"))); ++ (id)produceUnavailable __attribute__((swift_name("produceUnavailable()"))); ++ (NSString *)consumeUnavailableParam:(id)param __attribute__((swift_name("consumeUnavailable(param:)"))); ++ (id)createUnavailableInterface __attribute__((swift_name("createUnavailableInterface()"))); ++ (NSString * _Nullable)useOfNullableUnavailableInterfaceParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableInterface(param:)"))); ++ (id)createUnavailableEnum __attribute__((swift_name("createUnavailableEnum()"))); ++ (NSString *)useOfUnavailableEnumParam:(id)param __attribute__((swift_name("useOfUnavailableEnum(param:)"))); ++ (NSString *)useOfNullableUnavailableEnumParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableEnum(param:)"))); ++ (id)getUnavailableObject __attribute__((swift_name("getUnavailableObject()"))); ++ (NSString *)useOfUnavailableObjectParam:(id)param __attribute__((swift_name("useOfUnavailableObject(param:)"))); ++ (NSString * _Nullable)useOfNullableUnavailableObjectParam:(id _Nullable)param __attribute__((swift_name("useOfNullableUnavailableObject(param:)"))); ++ (KtSealedClass *)createSealedClass __attribute__((swift_name("createSealedClass()"))); ++ (NSString *)useSealedClassParam:(KtSealedClass *)param __attribute__((swift_name("useSealedClass(param:)"))); ++ (NSString *)useUnavailableA:(id)a __attribute__((swift_name("useUnavailable(a:)"))); +@end + __attribute__((swift_name("InterfaceNameManglingI1"))) @protocol KtInterfaceNameManglingI1 @required diff --git a/kotlin-native/backend.native/tests/objcexport/hiddenfromobjc.kt b/kotlin-native/backend.native/tests/objcexport/hiddenfromobjc.kt new file mode 100644 index 00000000000..faa18f578fd --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/hiddenfromobjc.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package hiddenfromobjc + +import kotlin.experimental.ExperimentalObjCRefinement + +@OptIn(ExperimentalObjCRefinement::class) +@HiddenFromObjC +data class ClassNotAvailableInSwift(val param: String) + +// Check that inner and nested classes are hidden if enclosing class is hidden +@OptIn(ExperimentalObjCRefinement::class) +@HiddenFromObjC +class ParentClass { + class NestedClass { + class DeeplyNestedClass + } + + inner class InnerClass +} + +fun useOfUnavailableClass(param: ClassNotAvailableInSwift): ClassNotAvailableInSwift { + return ClassNotAvailableInSwift("hi") +} + +fun useOfNullableUnavailableClass(param: ClassNotAvailableInSwift?): ClassNotAvailableInSwift? { + return null +} + +fun produceUnavailable(): ClassNotAvailableInSwift { + return ClassNotAvailableInSwift("hi") +} + +fun consumeUnavailable(param: ClassNotAvailableInSwift): String { + return param.param +} + +@OptIn(ExperimentalObjCRefinement::class) +@HiddenFromObjC +interface InterfaceNotAvailableInSwift { + fun f(): String +} + +fun createUnavailableInterface(): InterfaceNotAvailableInSwift { + return object : InterfaceNotAvailableInSwift { + override fun f(): String = "I'm actually unavailable, call me later." + } +} + +fun useOfNullableUnavailableInterface(param: InterfaceNotAvailableInSwift?): String? { + return param?.f() ?: "null" +} + +@OptIn(ExperimentalObjCRefinement::class) +@HiddenFromObjC +enum class UnavailableEnum { + A, B, C; +} + +fun createUnavailableEnum(): UnavailableEnum { + return UnavailableEnum.A +} + +fun useOfUnavailableEnum(param: UnavailableEnum): String { + return param.toString() +} + +fun useOfNullableUnavailableEnum(param: UnavailableEnum?): String { + return param?.toString() ?: "null" +} + +@OptIn(ExperimentalObjCRefinement::class) +@HiddenFromObjC +object UnavailableObject { + val field: String = "objectField" +} + +fun getUnavailableObject(): UnavailableObject { + return UnavailableObject +} + +fun useOfUnavailableObject(param:UnavailableObject):String { + return param.field +} + +fun useOfNullableUnavailableObject(param:UnavailableObject?):String? { + return param?.field ?: "null" +} + + +sealed class SealedClass { + + @OptIn(ExperimentalObjCRefinement::class) + @HiddenFromObjC + class A : SealedClass() + + class B : SealedClass() + + @OptIn(ExperimentalObjCRefinement::class) + @HiddenFromObjC + object C : SealedClass() +} + +fun createSealedClass(): SealedClass { + return SealedClass.A() +} + +fun useSealedClass(param: SealedClass): String { + return when (param) { + is SealedClass.A -> "A" + is SealedClass.B -> "B" + SealedClass.C -> "C" + } +} + +fun useUnavailable(a : T): String { + return a.f() +} + +class WrapperOverUnavailable(val arg: T) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/hiddenfromobjc.swift b/kotlin-native/backend.native/tests/objcexport/hiddenfromobjc.swift new file mode 100644 index 00000000000..2d3de46f372 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/hiddenfromobjc.swift @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +private func testUnavailableEnum() throws { + try assertEquals(actual: HiddenfromobjcKt.useOfUnavailableEnum(param: HiddenfromobjcKt.createUnavailableEnum()), expected: "A") + try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableEnum(param: nil), expected: "null") + try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableEnum(param: HiddenfromobjcKt.createUnavailableEnum()), expected: "A") +} + +private func testUnavailableObject() throws { + try assertEquals(actual: HiddenfromobjcKt.useOfUnavailableObject(param: HiddenfromobjcKt.getUnavailableObject()), expected: "objectField") + try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableObject(param: HiddenfromobjcKt.getUnavailableObject()), expected: "objectField") + try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableObject(param: nil), expected: "null") +} + +private func testUnavailableInterface() throws { + try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableInterface( + param: HiddenfromobjcKt.createUnavailableInterface()), + expected: "I'm actually unavailable, call me later." + ) + try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableInterface(param: nil), expected: "null") +} + +private func testSealedClass() throws { + try assertEquals(actual: HiddenfromobjcKt.useSealedClass(param: HiddenfromobjcKt.createSealedClass()), expected: "A") + try assertEquals(actual: HiddenfromobjcKt.useSealedClass(param: SealedClass.B()), expected: "B") +} + +private func testUnavailableGenerics() throws { + try assertEquals( + actual: HiddenfromobjcKt.useUnavailable(a: HiddenfromobjcKt.createUnavailableInterface()), + expected: "I'm actually unavailable, call me later." + ) + + let wrapper = WrapperOverUnavailable(arg: HiddenfromobjcKt.createUnavailableInterface() as AnyObject) + try assertEquals( + actual: HiddenfromobjcKt.useUnavailable(a: wrapper.arg), + expected: "I'm actually unavailable, call me later." + ) +} + + +class HiddenfromobjcTests : SimpleTestProvider { + override init() { + super.init() + + // Here we check that even if type is erased from Objective-C declarations, we still able to use them properly with proper objects. + test("testUnavailableEnum", testUnavailableEnum) + test("testUnavailableObject", testUnavailableObject) + test("testUnavailableInterface", testUnavailableInterface) + test("testSealedClass", testSealedClass) + test("testUnavailableGenerics", testUnavailableGenerics) + } +} \ No newline at end of file