[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(
|
||||
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(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() {
|
||||
|
||||
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) {
|
||||
if (declaration.classKind != ClassKind.ANNOTATION_CLASS) return
|
||||
|
||||
@@ -25,7 +25,7 @@ public annotation class ShouldRefineInSwift
|
||||
package plugin
|
||||
|
||||
@HidesFromObjC
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class PluginHiddenFromObjC
|
||||
|
||||
@@ -45,7 +45,7 @@ import plugin.PluginShouldRefineInSwift
|
||||
annotation class MyRefinedAnnotationA
|
||||
|
||||
<!INVALID_OBJC_REFINEMENT_TARGETS!>@HidesFromObjC<!>
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class MyRefinedAnnotationB
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ public interface InterfaceB {
|
||||
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 open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
@@ -146,7 +146,7 @@ package kotlin {
|
||||
|
||||
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 open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
|
||||
+27
@@ -596,9 +596,36 @@ private class BackendChecker(
|
||||
if (declaration.isKotlinObjCClass()) {
|
||||
checkKotlinObjCClass(declaration)
|
||||
}
|
||||
checkHiddenFromObjCRestrictions(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) {
|
||||
|
||||
+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 =
|
||||
shouldBeVisible(descriptor) && !isSpecialMapped(descriptor) && !descriptor.defaultType.isObjCObjectType()
|
||||
|
||||
@@ -175,7 +185,7 @@ internal fun ObjCExportMapper.shouldBeVisible(descriptor: ClassDescriptor): Bool
|
||||
descriptor.isEffectivelyPublicApi && when (descriptor.kind) {
|
||||
ClassKind.CLASS, ClassKind.INTERFACE, ClassKind.ENUM_CLASS, ClassKind.OBJECT -> true
|
||||
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 =
|
||||
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)
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@@ -122,10 +122,10 @@ public actual annotation class ObjCName(actual val name: String = "", actual val
|
||||
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
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@MustBeDocumented
|
||||
@ExperimentalObjCRefinement
|
||||
|
||||
@@ -69,12 +69,12 @@ expect annotation class FreezingIsDeprecated
|
||||
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
|
||||
* 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)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@@ -85,10 +85,10 @@ public expect annotation class ObjCName(val name: String = "", val swiftName: St
|
||||
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
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@MustBeDocumented
|
||||
@OptionalExpectation
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
)
|
||||
put(
|
||||
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 {
|
||||
|
||||
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) {
|
||||
if (descriptor !is ClassDescriptor || descriptor.kind != ClassKind.ANNOTATION_CLASS) return
|
||||
|
||||
Reference in New Issue
Block a user