[K/N] KT-56464: implementation of HiddenFromObjC for classes in backend
This commit is contained in:
committed by
Space Team
parent
6651e6ed8c
commit
fce878d63a
+1
-1
@@ -61,7 +61,7 @@ object FirNativeErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
)
|
)
|
||||||
map.put(
|
map.put(
|
||||||
INVALID_OBJC_REFINEMENT_TARGETS,
|
INVALID_OBJC_REFINEMENT_TARGETS,
|
||||||
"Refines annotations are only applicable to annotations with targets FUNCTION and/or PROPERTY"
|
"Refines annotations are only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY"
|
||||||
)
|
)
|
||||||
map.put(INAPPLICABLE_OBJC_NAME, "@ObjCName is not applicable on overrides")
|
map.put(INAPPLICABLE_OBJC_NAME, "@ObjCName is not applicable on overrides")
|
||||||
map.put(INVALID_OBJC_NAME, "@ObjCName should have a name and/or swiftName")
|
map.put(INVALID_OBJC_NAME, "@ObjCName should have a name and/or swiftName")
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
|||||||
|
|
||||||
object FirNativeObjCRefinementAnnotationChecker : FirRegularClassChecker() {
|
object FirNativeObjCRefinementAnnotationChecker : FirRegularClassChecker() {
|
||||||
|
|
||||||
private val supportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY)
|
private val supportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS)
|
||||||
|
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration.classKind != ClassKind.ANNOTATION_CLASS) return
|
if (declaration.classKind != ClassKind.ANNOTATION_CLASS) return
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public annotation class ShouldRefineInSwift
|
|||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
@HidesFromObjC
|
@HidesFromObjC
|
||||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
annotation class PluginHiddenFromObjC
|
annotation class PluginHiddenFromObjC
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ import plugin.PluginShouldRefineInSwift
|
|||||||
annotation class MyRefinedAnnotationA
|
annotation class MyRefinedAnnotationA
|
||||||
|
|
||||||
<!INVALID_OBJC_REFINEMENT_TARGETS!>@HidesFromObjC<!>
|
<!INVALID_OBJC_REFINEMENT_TARGETS!>@HidesFromObjC<!>
|
||||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FILE)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
annotation class MyRefinedAnnotationB
|
annotation class MyRefinedAnnotationB
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public interface InterfaceB {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.native.HidesFromObjC @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class MyRefinedAnnotationB : kotlin.Annotation {
|
@kotlin.native.HidesFromObjC @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FILE}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class MyRefinedAnnotationB : kotlin.Annotation {
|
||||||
public constructor MyRefinedAnnotationB()
|
public constructor MyRefinedAnnotationB()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
@@ -146,7 +146,7 @@ package kotlin {
|
|||||||
|
|
||||||
package plugin {
|
package plugin {
|
||||||
|
|
||||||
@kotlin.native.HidesFromObjC @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class PluginHiddenFromObjC : kotlin.Annotation {
|
@kotlin.native.HidesFromObjC @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class PluginHiddenFromObjC : kotlin.Annotation {
|
||||||
public constructor PluginHiddenFromObjC()
|
public constructor PluginHiddenFromObjC()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
|||||||
+27
@@ -596,9 +596,36 @@ private class BackendChecker(
|
|||||||
if (declaration.isKotlinObjCClass()) {
|
if (declaration.isKotlinObjCClass()) {
|
||||||
checkKotlinObjCClass(declaration)
|
checkKotlinObjCClass(declaration)
|
||||||
}
|
}
|
||||||
|
checkHiddenFromObjCRestrictions(declaration)
|
||||||
super.visitClass(declaration)
|
super.visitClass(declaration)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrClass.isHiddenFromObjC(): Boolean {
|
||||||
|
return annotations.any { annotationCall ->
|
||||||
|
val annotationClass = annotationCall.symbol.owner.parentAsClass
|
||||||
|
annotationClass.annotations.hasAnnotation(KonanFqNames.hidesFromObjC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkHiddenFromObjCRestrictions(declaration: IrClass) {
|
||||||
|
// If declaration itself. is marked as hidden, we don't need to do anything
|
||||||
|
if (declaration.isHiddenFromObjC()) return
|
||||||
|
// Enum entries inherit from their classes, so if enum class is marked as hidden, there is no need to
|
||||||
|
// produce additional errors.
|
||||||
|
if (declaration.kind == ClassKind.ENUM_ENTRY) return
|
||||||
|
// Private and local classes does not leak to Objective-C API surface, so it is OK for them
|
||||||
|
// to inherit from hidden types.
|
||||||
|
if (DescriptorVisibilities.isPrivate(declaration.visibility) || declaration.isLocal) return
|
||||||
|
if (declaration.superClass?.isHiddenFromObjC() == true) {
|
||||||
|
reportError(declaration, "Only @HiddenFromObjC declaration can inherit from class annotated with @HiddenFromObjC")
|
||||||
|
}
|
||||||
|
declaration.getSuperInterfaces().forEach {
|
||||||
|
if (it.isHiddenFromObjC()) {
|
||||||
|
reportError(declaration, "Only @HiddenFromObjC declaration can implement interface annotated with @HiddenFromObjC")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun BackendChecker.checkCanGenerateCCall(expression: IrCall, isInvoke: Boolean) {
|
private fun BackendChecker.checkCanGenerateCCall(expression: IrCall, isInvoke: Boolean) {
|
||||||
|
|||||||
+11
-1
@@ -108,6 +108,16 @@ private fun CallableMemberDescriptor.isHiddenFromObjC(): Boolean = when {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given class or its enclosing declaration is marked as @HiddenFromObjC.
|
||||||
|
*/
|
||||||
|
internal fun ClassDescriptor.isHiddenFromObjC(): Boolean = when {
|
||||||
|
(this.containingDeclaration as? ClassDescriptor)?.isHiddenFromObjC() == true -> true
|
||||||
|
else -> annotations.any { annotation ->
|
||||||
|
annotation.annotationClass?.annotations?.any { it.fqName == KonanFqNames.hidesFromObjC } == true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun ObjCExportMapper.shouldBeExposed(descriptor: ClassDescriptor): Boolean =
|
internal fun ObjCExportMapper.shouldBeExposed(descriptor: ClassDescriptor): Boolean =
|
||||||
shouldBeVisible(descriptor) && !isSpecialMapped(descriptor) && !descriptor.defaultType.isObjCObjectType()
|
shouldBeVisible(descriptor) && !isSpecialMapped(descriptor) && !descriptor.defaultType.isObjCObjectType()
|
||||||
|
|
||||||
@@ -175,7 +185,7 @@ internal fun ObjCExportMapper.shouldBeVisible(descriptor: ClassDescriptor): Bool
|
|||||||
descriptor.isEffectivelyPublicApi && when (descriptor.kind) {
|
descriptor.isEffectivelyPublicApi && when (descriptor.kind) {
|
||||||
ClassKind.CLASS, ClassKind.INTERFACE, ClassKind.ENUM_CLASS, ClassKind.OBJECT -> true
|
ClassKind.CLASS, ClassKind.INTERFACE, ClassKind.ENUM_CLASS, ClassKind.OBJECT -> true
|
||||||
ClassKind.ENUM_ENTRY, ClassKind.ANNOTATION_CLASS -> false
|
ClassKind.ENUM_ENTRY, ClassKind.ANNOTATION_CLASS -> false
|
||||||
} && !descriptor.isExpect && !descriptor.isInlined() && !isHiddenByDeprecation(descriptor)
|
} && !descriptor.isExpect && !descriptor.isInlined() && !isHiddenByDeprecation(descriptor) && !descriptor.isHiddenFromObjC()
|
||||||
|
|
||||||
private fun ObjCExportMapper.isBase(descriptor: CallableMemberDescriptor): Boolean =
|
private fun ObjCExportMapper.isBase(descriptor: CallableMemberDescriptor): Boolean =
|
||||||
descriptor.overriddenDescriptors.all { !shouldBeExposed(it) }
|
descriptor.overriddenDescriptors.all { !shouldBeExposed(it) }
|
||||||
|
|||||||
@@ -107,12 +107,12 @@ public actual annotation class CName(actual val externName: String = "", actual
|
|||||||
public actual annotation class ObjCName(actual val name: String = "", actual val swiftName: String = "", actual val exact: Boolean = false)
|
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.
|
* Meta-annotation that instructs the Kotlin compiler to remove the annotated class, 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
|
* 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.
|
* to have the original declarations automatically removed from the public API.
|
||||||
*
|
*
|
||||||
* Note: only annotations with [AnnotationTarget.FUNCTION] and/or [AnnotationTarget.PROPERTY] are supported.
|
* Note: only annotations with [AnnotationTarget.CLASS], [AnnotationTarget.FUNCTION] and/or [AnnotationTarget.PROPERTY] are supported.
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
@@ -122,10 +122,10 @@ public actual annotation class ObjCName(actual val name: String = "", actual val
|
|||||||
public actual annotation class HidesFromObjC
|
public actual annotation class HidesFromObjC
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructs the Kotlin compiler to remove this function or property from the public Objective-C API.
|
* Instructs the Kotlin compiler to remove this class, function or property from the public Objective-C API.
|
||||||
*/
|
*/
|
||||||
@HidesFromObjC
|
@HidesFromObjC
|
||||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
@MustBeDocumented
|
@MustBeDocumented
|
||||||
@ExperimentalObjCRefinement
|
@ExperimentalObjCRefinement
|
||||||
|
|||||||
@@ -69,12 +69,12 @@ expect annotation class FreezingIsDeprecated
|
|||||||
public expect annotation class ObjCName(val name: String = "", val swiftName: String = "", val exact: Boolean = false)
|
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.
|
* Meta-annotation that instructs the Kotlin compiler to remove the annotated class, 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
|
* 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.
|
* to have the original declarations automatically removed from the public API.
|
||||||
*
|
*
|
||||||
* Note: only annotations with [AnnotationTarget.FUNCTION] and/or [AnnotationTarget.PROPERTY] are supported.
|
* Note: only annotations with [AnnotationTarget.CLASS], [AnnotationTarget.FUNCTION] and/or [AnnotationTarget.PROPERTY] are supported.
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
@@ -85,10 +85,10 @@ public expect annotation class ObjCName(val name: String = "", val swiftName: St
|
|||||||
public expect annotation class HidesFromObjC()
|
public expect annotation class HidesFromObjC()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructs the Kotlin compiler to remove this function or property from the public Objective-C API.
|
* Instructs the Kotlin compiler to remove this class, function or property from the public Objective-C API.
|
||||||
*/
|
*/
|
||||||
@HidesFromObjC
|
@HidesFromObjC
|
||||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
@MustBeDocumented
|
@MustBeDocumented
|
||||||
@OptionalExpectation
|
@OptionalExpectation
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
|||||||
)
|
)
|
||||||
put(
|
put(
|
||||||
ErrorsNative.INVALID_OBJC_REFINEMENT_TARGETS,
|
ErrorsNative.INVALID_OBJC_REFINEMENT_TARGETS,
|
||||||
"Refines annotations are only applicable to annotations with targets FUNCTION and/or PROPERTY"
|
"Refines annotations are only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCRefinementChecke
|
|||||||
|
|
||||||
object NativeObjCRefinementAnnotationChecker : DeclarationChecker {
|
object NativeObjCRefinementAnnotationChecker : DeclarationChecker {
|
||||||
|
|
||||||
private val supportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY)
|
private val supportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS)
|
||||||
|
|
||||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||||
if (descriptor !is ClassDescriptor || descriptor.kind != ClassKind.ANNOTATION_CLASS) return
|
if (descriptor !is ClassDescriptor || descriptor.kind != ClassKind.ANNOTATION_CLASS) return
|
||||||
|
|||||||
Reference in New Issue
Block a user