diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt index 68e970389da..4b90637d80e 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt @@ -38,5 +38,8 @@ object KonanFqNames { val eagerInitialization = FqName("kotlin.native.EagerInitialization") val noReorderFields = FqName("kotlin.native.internal.NoReorderFields") val objCName = FqName("kotlin.native.ObjCName") + val hidesFromObjC = FqName("kotlin.native.HidesFromObjC") + val refinesInSwift = FqName("kotlin.native.RefinesInSwift") + val shouldRefineInSwift = FqName("kotlin.native.ShouldRefineInSwift") val reflectionPackageName = FqName("kotlin.native.internal.ReflectionPackageName") } 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 187233d7104..e4bcafcf35b 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 @@ -613,7 +613,7 @@ internal class ObjCExportTranslatorImpl( val getterSelector = getSelector(baseProperty.getter!!) val getterName: String? = if (getterSelector != name) getterSelector else null - val declarationAttributes = mutableListOf(swiftNameAttribute(propertyName.swiftName)) + val declarationAttributes = mutableListOf(property.getSwiftPrivateAttribute() ?: swiftNameAttribute(propertyName.swiftName)) declarationAttributes.addIfNotNull(mapper.getDeprecation(property)?.toDeprecationAttribute()) val visibilityComments = visibilityComments(property.visibility, "property") @@ -701,7 +701,7 @@ internal class ObjCExportTranslatorImpl( val swiftName = namer.getSwiftName(baseMethod) val attributes = mutableListOf() - attributes += swiftNameAttribute(swiftName) + attributes += method.getSwiftPrivateAttribute() ?: swiftNameAttribute(swiftName) if (baseMethodBridge.returnBridge is MethodBridge.ReturnValue.WithError.ZeroForError && baseMethodBridge.returnBridge.successMayBeZero) { @@ -806,7 +806,7 @@ internal class ObjCExportTranslatorImpl( } } - private val mustBeDocumentedAnnotationsStopList = setOf(StandardNames.FqNames.deprecated, KonanFqNames.objCName) + private val mustBeDocumentedAnnotationsStopList = setOf(StandardNames.FqNames.deprecated, KonanFqNames.objCName, KonanFqNames.shouldRefineInSwift) private fun mustBeDocumentedAnnotations(annotations: Annotations): List { return annotations.mapNotNull { it -> it.annotationClass?.let { annotationClass -> @@ -1431,6 +1431,17 @@ private fun DeprecationInfo.toDeprecationAttribute(): String { private fun renderDeprecationAttribute(attribute: String, message: String) = "$attribute(${quoteAsCStringLiteral(message)})" +private fun CallableMemberDescriptor.isRefinedInSwift(): Boolean = when { + // Note: the front-end checker requires all overridden descriptors to be either refined or not refined. + overriddenDescriptors.isNotEmpty() -> overriddenDescriptors.first().isRefinedInSwift() + else -> annotations.any { annotation -> + annotation.annotationClass?.annotations?.any { it.fqName == KonanFqNames.refinesInSwift } == true + } +} + +private fun CallableMemberDescriptor.getSwiftPrivateAttribute(): String? = + if (isRefinedInSwift()) "swift_private" else null + private fun quoteAsCStringLiteral(str: String): String = buildString { append('"') for (c in str) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt index 443ed722696..1952e2d9f89 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt @@ -97,9 +97,18 @@ internal fun ObjCExportMapper.shouldBeExposed(descriptor: CallableMemberDescript // KT-42641. Don't expose componentN methods of data classes // because they are useless in Objective-C/Swift. isComponentNMethod(descriptor) && descriptor.overriddenDescriptors.isEmpty() -> false + descriptor.isHiddenFromObjC() -> false else -> true } +private fun CallableMemberDescriptor.isHiddenFromObjC(): Boolean = when { + // Note: the front-end checker requires all overridden descriptors to be either refined or not refined. + overriddenDescriptors.isNotEmpty() -> overriddenDescriptors.first().isHiddenFromObjC() + else -> annotations.any { annotation -> + annotation.annotationClass?.annotations?.any { it.fqName == KonanFqNames.hidesFromObjC } == true + } +} + internal fun ObjCExportMapper.shouldBeExposed(descriptor: ClassDescriptor): Boolean = shouldBeVisible(descriptor) && !isSpecialMapped(descriptor) && !descriptor.defaultType.isObjCObjectType() diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h index 2c94be21dee..e7d55a1d9ea 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h @@ -1418,6 +1418,40 @@ __attribute__((swift_name("OverrideMethodsOfAnyKt"))) + (BOOL)testObj:(id)obj other:(id)other swift:(BOOL)swift error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("test(obj:other:swift:)"))); @end +__attribute__((swift_name("RefinedClassA"))) +@interface KtRefinedClassA : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)fooRefined __attribute__((swift_private)); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("RefinedClassB"))) +@interface KtRefinedClassB : KtRefinedClassA +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)fooRefined __attribute__((swift_private)); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("RefinedKt"))) +@interface KtRefinedKt : KtBase ++ (NSString *)fooRefined __attribute__((swift_private)); + +/** + * @note annotations + * refined.MyShouldRefineInSwift +*/ ++ (NSString *)myFooRefined __attribute__((swift_private)); +@property (class, readonly) NSString *barRefined __attribute__((swift_private)); + +/** + * @note annotations + * refined.MyShouldRefineInSwift +*/ +@property (class, readonly) NSString *myBarRefined __attribute__((swift_private)); +@end + __attribute__((swift_name("Person"))) @interface KtPerson : KtBase @end diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h index 1f3b3e98f89..b6ef75db3be 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h @@ -1353,6 +1353,40 @@ __attribute__((swift_name("OverrideMethodsOfAnyKt"))) + (BOOL)testObj:(id)obj other:(id)other swift:(BOOL)swift error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("test(obj:other:swift:)"))); @end +__attribute__((swift_name("RefinedClassA"))) +@interface KtRefinedClassA : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)fooRefined __attribute__((swift_private)); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("RefinedClassB"))) +@interface KtRefinedClassB : KtRefinedClassA +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)fooRefined __attribute__((swift_private)); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("RefinedKt"))) +@interface KtRefinedKt : KtBase ++ (NSString *)fooRefined __attribute__((swift_private)); + +/** + * @note annotations + * refined.MyShouldRefineInSwift +*/ ++ (NSString *)myFooRefined __attribute__((swift_private)); +@property (class, readonly) NSString *barRefined __attribute__((swift_private)); + +/** + * @note annotations + * refined.MyShouldRefineInSwift +*/ +@property (class, readonly) NSString *myBarRefined __attribute__((swift_private)); +@end + __attribute__((swift_name("Person"))) @interface KtPerson : KtBase @end diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h index a3a94bb30bc..ad94862b71d 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h @@ -1353,6 +1353,40 @@ __attribute__((swift_name("OverrideMethodsOfAnyKt"))) + (BOOL)testObj:(id)obj other:(id)other swift:(BOOL)swift error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("test(obj:other:swift:)"))); @end +__attribute__((swift_name("RefinedClassA"))) +@interface KtRefinedClassA : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)fooRefined __attribute__((swift_private)); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("RefinedClassB"))) +@interface KtRefinedClassB : KtRefinedClassA +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)fooRefined __attribute__((swift_private)); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("RefinedKt"))) +@interface KtRefinedKt : KtBase ++ (NSString *)fooRefined __attribute__((swift_private)); + +/** + * @note annotations + * refined.MyShouldRefineInSwift +*/ ++ (NSString *)myFooRefined __attribute__((swift_private)); +@property (class, readonly) NSString *barRefined __attribute__((swift_private)); + +/** + * @note annotations + * refined.MyShouldRefineInSwift +*/ +@property (class, readonly) NSString *myBarRefined __attribute__((swift_private)); +@end + __attribute__((swift_name("Person"))) @interface KtPerson : KtBase @end diff --git a/kotlin-native/backend.native/tests/objcexport/refined.kt b/kotlin-native/backend.native/tests/objcexport/refined.kt new file mode 100644 index 00000000000..8389f316e9a --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/refined.kt @@ -0,0 +1,71 @@ +/* + * 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 refined + +import kotlin.experimental.ExperimentalObjCRefinement + +@ExperimentalObjCRefinement +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@HidesFromObjC +annotation class MyHiddenFromObjC + +@ExperimentalObjCRefinement +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@RefinesInSwift +annotation class MyShouldRefineInSwift + +@OptIn(ExperimentalObjCRefinement::class) +@HiddenFromObjC +fun foo(): Int = 1 + +@OptIn(ExperimentalObjCRefinement::class) +@ShouldRefineInSwift +fun fooRefined(): String = foo().toString() + +@OptIn(ExperimentalObjCRefinement::class) +@MyHiddenFromObjC +fun myFoo(): Int = 2 + +@OptIn(ExperimentalObjCRefinement::class) +@MyShouldRefineInSwift +fun myFooRefined(): String = myFoo().toString() + +@OptIn(ExperimentalObjCRefinement::class) +@HiddenFromObjC +val bar: Int = 3 + +@OptIn(ExperimentalObjCRefinement::class) +@ShouldRefineInSwift +val barRefined: String get() = bar.toString() + +@OptIn(ExperimentalObjCRefinement::class) +@MyHiddenFromObjC +val myBar: Int = 4 + +@OptIn(ExperimentalObjCRefinement::class) +@MyShouldRefineInSwift +val myBarRefined: String get() = myBar.toString() + +open class RefinedClassA { + @OptIn(ExperimentalObjCRefinement::class) + @HiddenFromObjC + open fun foo(): Int = 1 + @OptIn(ExperimentalObjCRefinement::class) + @ShouldRefineInSwift + open fun fooRefined(): String = foo().toString() +} + +class RefinedClassB: RefinedClassA() { + override fun foo(): Int = 2 + override fun fooRefined(): String { + val foo = foo() + return "$foo$foo" + } +} diff --git a/kotlin-native/backend.native/tests/objcexport/refined.swift b/kotlin-native/backend.native/tests/objcexport/refined.swift new file mode 100644 index 00000000000..3867f1e4d65 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/refined.swift @@ -0,0 +1,50 @@ +import Kt + +extension RefinedKt { + static func foo() -> Int { + return Int(RefinedKt.__fooRefined())! * 2 + } + + static func myFoo() -> Int { + return Int(RefinedKt.__myFooRefined())! * 2 + } + + static var bar: Int { + return Int(RefinedKt.__barRefined)! * 2 + } + + static var myBar: Int { + return Int(RefinedKt.__myBarRefined)! * 2 + } +} + +extension RefinedClassA { + func foo() -> Int { + return Int(__fooRefined())! * 2 + } +} + +private func testSwiftRefinements() throws { + try assertEquals(actual: RefinedKt.foo(), expected: 2) + try assertEquals(actual: RefinedKt.bar, expected: 6) +} + +private func testMySwiftRefinements() throws { + try assertEquals(actual: RefinedKt.myFoo(), expected: 4) + try assertEquals(actual: RefinedKt.myBar, expected: 8) +} + +private func testInheritedRefinements() throws { + try assertEquals(actual: RefinedClassA().foo(), expected: 2) + try assertEquals(actual: RefinedClassB().foo(), expected: 44) +} + +class RefinedTests : SimpleTestProvider { + override init() { + super.init() + + test("TestSwiftRefinements", testSwiftRefinements) + test("TestMySwiftRefinements", testMySwiftRefinements) + test("TestInheritedRefinements", testInheritedRefinements) + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Annotations.kt index 4c0413273fd..dd459615c80 100644 --- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Annotations.kt +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Annotations.kt @@ -6,6 +6,7 @@ package kotlin.native import kotlin.experimental.ExperimentalObjCName +import kotlin.experimental.ExperimentalObjCRefinement import kotlin.reflect.KClass /** @@ -100,3 +101,58 @@ public actual annotation class CName(actual val externName: String = "", actual @MustBeDocumented @ExperimentalObjCName public actual annotation class ObjCName(actual val name: String = "", actual val swiftName: String = "", actual val exact: Boolean = false) + +/** + * Meta-annotation that instructs the Kotlin compiler to remove the annotated function or property from the public Objective-C API. + * + * Annotation processors that refine the public Objective-C API can annotate their annotations with this meta-annotation + * to have the original declarations automatically removed from the public API. + * + * Note: only annotations with [AnnotationTarget.FUNCTION] and/or [AnnotationTarget.PROPERTY] are supported. + */ +@Target(AnnotationTarget.ANNOTATION_CLASS) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@ExperimentalObjCRefinement +public actual annotation class HidesFromObjC + +/** + * Instructs the Kotlin compiler to remove this function or property from the public Objective-C API. + */ +@HidesFromObjC +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@ExperimentalObjCRefinement +public actual annotation class HiddenFromObjC + +/** + * Meta-annotation that instructs the Kotlin compiler to mark the annotated function or property as + * `swift_private` in the generated Objective-C API. + * + * Annotation processors that refine the public API in Swift can annotate their annotations with this meta-annotation + * to automatically hide the annotated declarations from Swift. + * + * See Apple's documentation of the [`NS_REFINED_FOR_SWIFT`](https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/improving_objective-c_api_declarations_for_swift) + * macro for more information on refining Objective-C declarations in Swift. + * + * Note: only annotations with [AnnotationTarget.FUNCTION] and/or [AnnotationTarget.PROPERTY] are supported. + */ +@Target(AnnotationTarget.ANNOTATION_CLASS) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@ExperimentalObjCRefinement +public actual annotation class RefinesInSwift + +/** + * Instructs the Kotlin compiler to mark this function or property as `swift_private` in the generated Objective-C API. + * + * See Apple's documentation of the [`NS_REFINED_FOR_SWIFT`](https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/improving_objective-c_api_declarations_for_swift) + * macro for more information on refining Objective-C declarations in Swift. + */ +@RefinesInSwift +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@ExperimentalObjCRefinement +public actual annotation class ShouldRefineInSwift diff --git a/libraries/stdlib/api/js-v1/kotlin.experimental.kt b/libraries/stdlib/api/js-v1/kotlin.experimental.kt index e00ee054662..f3e1f0633c5 100644 --- a/libraries/stdlib/api/js-v1/kotlin.experimental.kt +++ b/libraries/stdlib/api/js-v1/kotlin.experimental.kt @@ -38,6 +38,14 @@ public final annotation class ExperimentalObjCName : kotlin.Annotation { public constructor ExperimentalObjCName() } +@kotlin.RequiresOptIn +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.ANNOTATION_CLASS}) +@kotlin.annotation.Retention(value = AnnotationRetention.BINARY) +@kotlin.annotation.MustBeDocumented +public final annotation class ExperimentalObjCRefinement : kotlin.Annotation { + public constructor ExperimentalObjCRefinement() +} + @kotlin.RequiresOptIn(level = Level.ERROR) @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) diff --git a/libraries/stdlib/api/js/kotlin.experimental.kt b/libraries/stdlib/api/js/kotlin.experimental.kt index e00ee054662..f3e1f0633c5 100644 --- a/libraries/stdlib/api/js/kotlin.experimental.kt +++ b/libraries/stdlib/api/js/kotlin.experimental.kt @@ -38,6 +38,14 @@ public final annotation class ExperimentalObjCName : kotlin.Annotation { public constructor ExperimentalObjCName() } +@kotlin.RequiresOptIn +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.ANNOTATION_CLASS}) +@kotlin.annotation.Retention(value = AnnotationRetention.BINARY) +@kotlin.annotation.MustBeDocumented +public final annotation class ExperimentalObjCRefinement : kotlin.Annotation { + public constructor ExperimentalObjCRefinement() +} + @kotlin.RequiresOptIn(level = Level.ERROR) @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) diff --git a/libraries/stdlib/src/kotlin/annotations/NativeAnnotations.kt b/libraries/stdlib/src/kotlin/annotations/NativeAnnotations.kt index d0869d90d45..b5b7d8aee28 100644 --- a/libraries/stdlib/src/kotlin/annotations/NativeAnnotations.kt +++ b/libraries/stdlib/src/kotlin/annotations/NativeAnnotations.kt @@ -6,6 +6,7 @@ package kotlin.native import kotlin.experimental.ExperimentalObjCName +import kotlin.experimental.ExperimentalObjCRefinement /** * Makes top level function available from C/C++ code with the given name. @@ -65,3 +66,62 @@ expect annotation class FreezingIsDeprecated @OptionalExpectation @ExperimentalObjCName public expect annotation class ObjCName(val name: String = "", val swiftName: String = "", val exact: Boolean = false) + +/** + * Meta-annotation that instructs the Kotlin compiler to remove the annotated function or property from the public Objective-C API. + * + * Annotation processors that refine the public Objective-C API can annotate their annotations with this meta-annotation + * to have the original declarations automatically removed from the public API. + * + * Note: only annotations with [AnnotationTarget.FUNCTION] and/or [AnnotationTarget.PROPERTY] are supported. + */ +@Target(AnnotationTarget.ANNOTATION_CLASS) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@OptionalExpectation +@ExperimentalObjCRefinement +public expect annotation class HidesFromObjC() + +/** + * Instructs the Kotlin compiler to remove this function or property from the public Objective-C API. + */ +@HidesFromObjC +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@OptionalExpectation +@ExperimentalObjCRefinement +public expect annotation class HiddenFromObjC() + +/** + * Meta-annotation that instructs the Kotlin compiler to mark the annotated function or property as + * `swift_private` in the generated Objective-C API. + * + * Annotation processors that refine the public API in Swift can annotate their annotations with this meta-annotation + * to automatically hide the annotated declarations from Swift. + * + * See Apple's documentation of the [`NS_REFINED_FOR_SWIFT`](https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/improving_objective-c_api_declarations_for_swift) + * macro for more information on refining Objective-C declarations in Swift. + * + * Note: only annotations with [AnnotationTarget.FUNCTION] and/or [AnnotationTarget.PROPERTY] are supported. + */ +@Target(AnnotationTarget.ANNOTATION_CLASS) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@OptionalExpectation +@ExperimentalObjCRefinement +public expect annotation class RefinesInSwift() + +/** + * Instructs the Kotlin compiler to mark this function or property as `swift_private` in the generated Objective-C API. + * + * See Apple's documentation of the [`NS_REFINED_FOR_SWIFT`](https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/improving_objective-c_api_declarations_for_swift) + * macro for more information on refining Objective-C declarations in Swift. + */ +@RefinesInSwift +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@OptionalExpectation +@ExperimentalObjCRefinement +public expect annotation class ShouldRefineInSwift() diff --git a/libraries/stdlib/src/kotlin/experimental/ExperimentalObjCRefinement.kt b/libraries/stdlib/src/kotlin/experimental/ExperimentalObjCRefinement.kt new file mode 100644 index 00000000000..29672f584bc --- /dev/null +++ b/libraries/stdlib/src/kotlin/experimental/ExperimentalObjCRefinement.kt @@ -0,0 +1,15 @@ +/* + * 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 kotlin.experimental + +/** + * This annotation marks the experimental Objective-C export refinement annotations. + */ +@RequiresOptIn +@Target(AnnotationTarget.ANNOTATION_CLASS) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +public annotation class ExperimentalObjCRefinement diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index 4bf5a8982b7..b92e92a73eb 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -3148,6 +3148,9 @@ public final class kotlin/enums/EnumEntriesKt { public abstract interface annotation class kotlin/experimental/ExperimentalObjCName : java/lang/annotation/Annotation { } +public abstract interface annotation class kotlin/experimental/ExperimentalObjCRefinement : java/lang/annotation/Annotation { +} + public abstract interface annotation class kotlin/experimental/ExperimentalTypeInference : java/lang/annotation/Annotation { }