[K/N] KT-58562: Implement frontend checkers for HiddenFromObjC on classes
This commit is contained in:
committed by
Space Team
parent
f3a22e0ac4
commit
c57c34525f
+3
-1
@@ -46,7 +46,6 @@ object NATIVE_DIAGNOSTICS_LIST : DiagnosticList("FirNativeErrors") {
|
||||
parameter<FirBasedSymbol<*>>("declaration")
|
||||
parameter<Collection<FirRegularClassSymbol>>("containingClasses")
|
||||
}
|
||||
val INVALID_OBJC_REFINEMENT_TARGETS by error<KtElement>()
|
||||
val INAPPLICABLE_OBJC_NAME by error<KtElement>()
|
||||
val INVALID_OBJC_NAME by error<KtElement>()
|
||||
val INVALID_OBJC_NAME_CHARS by error<KtElement> {
|
||||
@@ -63,5 +62,8 @@ object NATIVE_DIAGNOSTICS_LIST : DiagnosticList("FirNativeErrors") {
|
||||
val INAPPLICABLE_EXACT_OBJC_NAME by error<KtElement>()
|
||||
val MISSING_EXACT_OBJC_NAME by error<KtElement>()
|
||||
val NON_LITERAL_OBJC_NAME_ARG by error<KtElement>()
|
||||
val INVALID_OBJC_HIDES_TARGETS by error<KtElement>()
|
||||
val INVALID_REFINES_IN_SWIFT_TARGETS by error<KtElement>()
|
||||
val SUBTYPE_OF_HIDDEN_FROM_OBJC by error<KtElement>()
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -35,7 +35,6 @@ object FirNativeErrors {
|
||||
val INVALID_CHARACTERS_NATIVE by deprecationError1<PsiElement, String>(ProhibitInvalidCharsInNativeIdentifiers, SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val REDUNDANT_SWIFT_REFINEMENT by error0<KtElement>()
|
||||
val INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE by error2<KtElement, FirBasedSymbol<*>, Collection<FirRegularClassSymbol>>()
|
||||
val INVALID_OBJC_REFINEMENT_TARGETS by error0<KtElement>()
|
||||
val INAPPLICABLE_OBJC_NAME by error0<KtElement>()
|
||||
val INVALID_OBJC_NAME by error0<KtElement>()
|
||||
val INVALID_OBJC_NAME_CHARS by error1<KtElement, String>()
|
||||
@@ -45,6 +44,9 @@ object FirNativeErrors {
|
||||
val INAPPLICABLE_EXACT_OBJC_NAME by error0<KtElement>()
|
||||
val MISSING_EXACT_OBJC_NAME by error0<KtElement>()
|
||||
val NON_LITERAL_OBJC_NAME_ARG by error0<KtElement>()
|
||||
val INVALID_OBJC_HIDES_TARGETS by error0<KtElement>()
|
||||
val INVALID_REFINES_IN_SWIFT_TARGETS by error0<KtElement>()
|
||||
val SUBTYPE_OF_HIDDEN_FROM_OBJC by error0<KtElement>()
|
||||
|
||||
init {
|
||||
RootDiagnosticRendererFactory.registerFactory(FirNativeErrorsDefaultMessages)
|
||||
|
||||
+10
-3
@@ -22,14 +22,16 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INCO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INCOMPATIBLE_THROWS_INHERITED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INCOMPATIBLE_THROWS_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_CHARACTERS_NATIVE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_HIDES_TARGETS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_NAME_CHARS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_NAME_FIRST_CHAR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_REFINEMENT_TARGETS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_REFINES_IN_SWIFT_TARGETS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.MISSING_EXACT_OBJC_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.REDUNDANT_SWIFT_REFINEMENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.NON_LITERAL_OBJC_NAME_ARG
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.SUBTYPE_OF_HIDDEN_FROM_OBJC
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.THROWS_LIST_EMPTY
|
||||
|
||||
object FirNativeErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
@@ -60,8 +62,12 @@ object FirNativeErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
SYMBOLS
|
||||
)
|
||||
map.put(
|
||||
INVALID_OBJC_REFINEMENT_TARGETS,
|
||||
"Refines annotations are only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY"
|
||||
INVALID_OBJC_HIDES_TARGETS,
|
||||
"@HidesFromObjC annotation is only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY"
|
||||
)
|
||||
map.put(
|
||||
INVALID_REFINES_IN_SWIFT_TARGETS,
|
||||
"@RefinesInSwift annotation is only applicable to annotations with targets 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")
|
||||
@@ -72,5 +78,6 @@ object FirNativeErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
map.put(INAPPLICABLE_EXACT_OBJC_NAME, "Exact @ObjCName is only applicable to classes, objects and interfaces")
|
||||
map.put(MISSING_EXACT_OBJC_NAME, "Exact @ObjCName is required to have an ObjC name")
|
||||
map.put(NON_LITERAL_OBJC_NAME_ARG, "@ObjCName accepts only literal string and boolean values")
|
||||
map.put(SUBTYPE_OF_HIDDEN_FROM_OBJC, "Only @HiddenFromObjC declaration can be a subtype of @HiddenFromObjC declaration")
|
||||
}
|
||||
}
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.fir.analysis.native.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
|
||||
/**
|
||||
* Check that the given class does not inherit from class or implements interface that is
|
||||
* marked as HiddenFromObjC (aka "marked with annotation that is marked as HidesFromObjC").
|
||||
*/
|
||||
object FirNativeHiddenFromObjCInheritanceChecker : FirRegularClassChecker() {
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
// Enum entries inherit from their enum class.
|
||||
if (declaration.classKind == ClassKind.ENUM_ENTRY) {
|
||||
return
|
||||
}
|
||||
// Non-public types do not leak to Objective-C API surface, so it is OK for them
|
||||
// to inherit from hidden types.
|
||||
if (!declaration.visibility.isPublicAPI) return
|
||||
val session = context.session
|
||||
// No need to report anything on class that is hidden itself.
|
||||
if (checkIsHiddenFromObjC(declaration.symbol, session)) {
|
||||
return
|
||||
}
|
||||
|
||||
val superTypes = declaration.superConeTypes
|
||||
.filterNot { it.isAny || it.isNullableAny }
|
||||
.mapNotNull { it.toSymbol(session) }
|
||||
|
||||
superTypes.firstOrNull { st -> checkIsHiddenFromObjC(st, session) }?.let {
|
||||
reporter.reportOn(declaration.source, FirNativeErrors.SUBTYPE_OF_HIDDEN_FROM_OBJC, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkContainingClassIsHidden(classSymbol: FirClassLikeSymbol<*>, session: FirSession): Boolean {
|
||||
return classSymbol.getContainingClassSymbol(session)?.let {
|
||||
if (checkIsHiddenFromObjC(it, session)) {
|
||||
true
|
||||
} else {
|
||||
checkContainingClassIsHidden(it, session)
|
||||
}
|
||||
} ?: false
|
||||
}
|
||||
|
||||
private fun checkIsHiddenFromObjC(classSymbol: FirClassLikeSymbol<*>, session: FirSession): Boolean {
|
||||
classSymbol.annotations.forEach { annotation ->
|
||||
val annotationClass = annotation.toAnnotationClassLikeSymbol(session) ?: return@forEach
|
||||
val objCExportMetaAnnotations = annotationClass.annotations.findMetaAnnotations(session)
|
||||
if (objCExportMetaAnnotations.hidesFromObjCAnnotation != null) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return checkContainingClassIsHidden(classSymbol, session)
|
||||
}
|
||||
+32
-17
@@ -6,9 +6,11 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.native.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker
|
||||
@@ -21,12 +23,13 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
|
||||
object FirNativeObjCRefinementAnnotationChecker : FirRegularClassChecker() {
|
||||
|
||||
private val supportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS)
|
||||
private val hidesFromObjCSupportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS)
|
||||
private val refinesInSwiftSupportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY)
|
||||
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration.classKind != ClassKind.ANNOTATION_CLASS) return
|
||||
val session = context.session
|
||||
val (objCAnnotation, swiftAnnotation) = declaration.findMetaAnnotations(session)
|
||||
val (objCAnnotation, swiftAnnotation) = declaration.annotations.findMetaAnnotations(session)
|
||||
if (objCAnnotation == null && swiftAnnotation == null) return
|
||||
if (objCAnnotation != null && swiftAnnotation != null) {
|
||||
reporter.reportOn(
|
||||
@@ -36,23 +39,35 @@ object FirNativeObjCRefinementAnnotationChecker : FirRegularClassChecker() {
|
||||
)
|
||||
}
|
||||
val targets = declaration.getAllowedAnnotationTargets(session)
|
||||
val unsupportedTargets = targets - supportedTargets
|
||||
if (unsupportedTargets.isNotEmpty()) {
|
||||
objCAnnotation?.let { reporter.reportOn(it.source, FirNativeErrors.INVALID_OBJC_REFINEMENT_TARGETS, context) }
|
||||
swiftAnnotation?.let { reporter.reportOn(it.source, FirNativeErrors.INVALID_OBJC_REFINEMENT_TARGETS, context) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClass.findMetaAnnotations(session: FirSession): Pair<FirAnnotation?, FirAnnotation?> {
|
||||
var objCAnnotation: FirAnnotation? = null
|
||||
var swiftAnnotation: FirAnnotation? = null
|
||||
for (annotation in annotations) {
|
||||
when (annotation.toAnnotationClassId(session)) {
|
||||
hidesFromObjCClassId -> objCAnnotation = annotation
|
||||
refinesInSwiftClassId -> swiftAnnotation = annotation
|
||||
objCAnnotation?.let {
|
||||
if ((targets - hidesFromObjCSupportedTargets).isNotEmpty()) {
|
||||
reporter.reportOn(it.source, FirNativeErrors.INVALID_OBJC_HIDES_TARGETS, context)
|
||||
}
|
||||
}
|
||||
swiftAnnotation?.let {
|
||||
if ((targets - refinesInSwiftSupportedTargets).isNotEmpty()) {
|
||||
reporter.reportOn(it.source, FirNativeErrors.INVALID_REFINES_IN_SWIFT_TARGETS, context)
|
||||
}
|
||||
if (objCAnnotation != null && swiftAnnotation != null) break
|
||||
}
|
||||
return objCAnnotation to swiftAnnotation
|
||||
}
|
||||
}
|
||||
|
||||
internal data class ObjCExportMetaAnnotations(
|
||||
val hidesFromObjCAnnotation: FirAnnotation?,
|
||||
val refinesInSwiftAnnotation: FirAnnotation?,
|
||||
)
|
||||
|
||||
internal fun List<FirAnnotation>.findMetaAnnotations(session: FirSession): ObjCExportMetaAnnotations {
|
||||
var objCAnnotation: FirAnnotation? = null
|
||||
var swiftAnnotation: FirAnnotation? = null
|
||||
for (annotation in this) {
|
||||
when (annotation.toAnnotationClassId(session)) {
|
||||
hidesFromObjCClassId -> objCAnnotation = annotation
|
||||
refinesInSwiftClassId -> swiftAnnotation = annotation
|
||||
}
|
||||
if (objCAnnotation != null && swiftAnnotation != null) break
|
||||
}
|
||||
return ObjCExportMetaAnnotations(objCAnnotation, swiftAnnotation)
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -30,6 +30,7 @@ object NativeDeclarationCheckers : DeclarationCheckers() {
|
||||
|
||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||
get() = setOf(
|
||||
FirNativeObjCRefinementAnnotationChecker
|
||||
FirNativeObjCRefinementAnnotationChecker,
|
||||
FirNativeHiddenFromObjCInheritanceChecker,
|
||||
)
|
||||
}
|
||||
|
||||
+71
-3
@@ -8,7 +8,7 @@ package kotlin.native
|
||||
annotation class HidesFromObjC
|
||||
|
||||
@HidesFromObjC
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class HiddenFromObjC
|
||||
|
||||
@@ -21,6 +21,11 @@ annotation class RefinesInSwift
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
public annotation class ShouldRefineInSwift
|
||||
|
||||
<!INVALID_REFINES_IN_SWIFT_TARGETS!>@RefinesInSwift<!>
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
public annotation class WrongShouldRefineInSwift
|
||||
|
||||
// FILE: plugin.kt
|
||||
package plugin
|
||||
|
||||
@@ -44,12 +49,12 @@ import plugin.PluginShouldRefineInSwift
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class MyRefinedAnnotationA
|
||||
|
||||
<!INVALID_OBJC_REFINEMENT_TARGETS!>@HidesFromObjC<!>
|
||||
<!INVALID_OBJC_HIDES_TARGETS!>@HidesFromObjC<!>
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class MyRefinedAnnotationB
|
||||
|
||||
<!INVALID_OBJC_REFINEMENT_TARGETS!>@RefinesInSwift<!>
|
||||
<!INVALID_REFINES_IN_SWIFT_TARGETS!>@RefinesInSwift<!>
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class MyRefinedAnnotationC
|
||||
|
||||
@@ -132,3 +137,66 @@ interface I {
|
||||
open class Derived2 : Derived() {
|
||||
override fun foo() {}
|
||||
}
|
||||
|
||||
@HiddenFromObjC
|
||||
open class OpenHiddenClass
|
||||
|
||||
<!SUBTYPE_OF_HIDDEN_FROM_OBJC!>class InheritsFromOpenHiddenClass : OpenHiddenClass()<!>
|
||||
|
||||
@HiddenFromObjC
|
||||
interface HiddenInterface
|
||||
|
||||
interface NotHiddenInterface
|
||||
|
||||
<!SUBTYPE_OF_HIDDEN_FROM_OBJC!>class ImplementsHiddenInterface : NotHiddenInterface, HiddenInterface<!>
|
||||
|
||||
<!SUBTYPE_OF_HIDDEN_FROM_OBJC!>class InheritsFromOpenHiddenClass2 : NotHiddenInterface, OpenHiddenClass()<!>
|
||||
|
||||
@HiddenFromObjC
|
||||
class OuterHidden {
|
||||
class Nested {
|
||||
open class Nested
|
||||
}
|
||||
}
|
||||
|
||||
<!SUBTYPE_OF_HIDDEN_FROM_OBJC!>class InheritsFromNested : OuterHidden.Nested.Nested()<!>
|
||||
|
||||
private class PrivateInheritsFromNested : OuterHidden.Nested.Nested()
|
||||
|
||||
internal class InternalInheritsFromNested : OuterHidden.Nested.Nested()
|
||||
|
||||
fun produceInstanceOfHidden(): OuterHidden.Nested.Nested {
|
||||
return object : OuterHidden.Nested.Nested() {}
|
||||
}
|
||||
|
||||
@HiddenFromObjC
|
||||
enum class MyHiddenEnum {
|
||||
A,
|
||||
B,
|
||||
C
|
||||
}
|
||||
|
||||
@HiddenFromObjC
|
||||
object MyHiddenObject
|
||||
|
||||
sealed class MySealedClass {
|
||||
@HiddenFromObjC
|
||||
class MyHiddenSealedVariant : MySealedClass()
|
||||
|
||||
class MyPublicVariant : MySealedClass()
|
||||
}
|
||||
|
||||
@HiddenFromObjC
|
||||
enum class MyHiddenNonTrivialEnum {
|
||||
A,
|
||||
B,
|
||||
C {
|
||||
override fun sayCheese(): String {
|
||||
return "Boo :("
|
||||
}
|
||||
};
|
||||
|
||||
open fun sayCheese(): String {
|
||||
return "Cheese!"
|
||||
}
|
||||
}
|
||||
|
||||
+163
-1
@@ -5,6 +5,7 @@ package
|
||||
@kotlin.native.HiddenFromObjC @plugin.PluginHiddenFromObjC public fun multipleObjCRefinementsFunction(): kotlin.Unit
|
||||
@kotlin.native.ShouldRefineInSwift @plugin.PluginShouldRefineInSwift public fun multipleSwiftRefinementsFunction(): kotlin.Unit
|
||||
@plugin.PluginHiddenFromObjC @plugin.PluginShouldRefineInSwift public fun pluginRefinedFunction(): kotlin.Unit
|
||||
public fun produceInstanceOfHidden(): OuterHidden.Nested.Nested
|
||||
|
||||
public open class Base {
|
||||
public constructor Base()
|
||||
@@ -54,6 +55,12 @@ public open class Derived2 : Derived {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.native.HiddenFromObjC public interface HiddenInterface {
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface I {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(): kotlin.Unit
|
||||
@@ -61,6 +68,34 @@ public interface I {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class ImplementsHiddenInterface : NotHiddenInterface, HiddenInterface {
|
||||
public constructor ImplementsHiddenInterface()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class InheritsFromNested : OuterHidden.Nested.Nested {
|
||||
public constructor InheritsFromNested()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class InheritsFromOpenHiddenClass : OpenHiddenClass {
|
||||
public constructor InheritsFromOpenHiddenClass()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class InheritsFromOpenHiddenClass2 : NotHiddenInterface, OpenHiddenClass {
|
||||
public constructor InheritsFromOpenHiddenClass2()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface InterfaceA {
|
||||
public abstract val barA: kotlin.Int
|
||||
public abstract val barB: kotlin.Int
|
||||
@@ -81,6 +116,63 @@ public interface InterfaceB {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class InternalInheritsFromNested : OuterHidden.Nested.Nested {
|
||||
public constructor InternalInheritsFromNested()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.native.HiddenFromObjC public final enum class MyHiddenEnum : kotlin.Enum<MyHiddenEnum> {
|
||||
enum entry A
|
||||
|
||||
enum entry B
|
||||
|
||||
enum entry C
|
||||
|
||||
private constructor MyHiddenEnum()
|
||||
@kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyHiddenEnum): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): MyHiddenEnum
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<MyHiddenEnum>
|
||||
}
|
||||
|
||||
@kotlin.native.HiddenFromObjC public final enum class MyHiddenNonTrivialEnum : kotlin.Enum<MyHiddenNonTrivialEnum> {
|
||||
enum entry A
|
||||
|
||||
enum entry B
|
||||
|
||||
enum entry C
|
||||
|
||||
private constructor MyHiddenNonTrivialEnum()
|
||||
@kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyHiddenNonTrivialEnum): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open fun sayCheese(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): MyHiddenNonTrivialEnum
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<MyHiddenNonTrivialEnum>
|
||||
}
|
||||
|
||||
@kotlin.native.HiddenFromObjC public object MyHiddenObject {
|
||||
private constructor MyHiddenObject()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.native.HidesFromObjC @kotlin.native.RefinesInSwift @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class MyRefinedAnnotationA : kotlin.Annotation {
|
||||
public constructor MyRefinedAnnotationA()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
@@ -108,13 +200,75 @@ public interface InterfaceB {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public sealed class MySealedClass {
|
||||
protected constructor MySealedClass()
|
||||
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 toString(): kotlin.String
|
||||
|
||||
@kotlin.native.HiddenFromObjC public final class MyHiddenSealedVariant : MySealedClass {
|
||||
public constructor MyHiddenSealedVariant()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class MyPublicVariant : MySealedClass {
|
||||
public constructor MyPublicVariant()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public interface NotHiddenInterface {
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.native.HiddenFromObjC public open class OpenHiddenClass {
|
||||
public constructor OpenHiddenClass()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.native.HiddenFromObjC public final class OuterHidden {
|
||||
public constructor OuterHidden()
|
||||
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 toString(): kotlin.String
|
||||
|
||||
public final class Nested {
|
||||
public constructor Nested()
|
||||
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 toString(): kotlin.String
|
||||
|
||||
public open class Nested {
|
||||
public constructor Nested()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class PrivateInheritsFromNested : OuterHidden.Nested.Nested {
|
||||
public constructor PrivateInheritsFromNested()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
public typealias HFOC = kotlin.native.HiddenFromObjC
|
||||
|
||||
package kotlin {
|
||||
|
||||
package kotlin.native {
|
||||
|
||||
@kotlin.native.HidesFromObjC @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class HiddenFromObjC : 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 HiddenFromObjC : kotlin.Annotation {
|
||||
public constructor HiddenFromObjC()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
@@ -141,6 +295,13 @@ package kotlin {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.native.RefinesInSwift @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class WrongShouldRefineInSwift : kotlin.Annotation {
|
||||
public constructor WrongShouldRefineInSwift()
|
||||
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 toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,3 +321,4 @@ package plugin {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-27
@@ -596,36 +596,9 @@ 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) {
|
||||
|
||||
+10
-2
@@ -63,8 +63,16 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
CommonRenderers.commaSeparated(Renderers.NAME)
|
||||
)
|
||||
put(
|
||||
ErrorsNative.INVALID_OBJC_REFINEMENT_TARGETS,
|
||||
"Refines annotations are only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY"
|
||||
ErrorsNative.INVALID_OBJC_HIDES_TARGETS,
|
||||
"@HidesFromObjC annotation is only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY"
|
||||
)
|
||||
put(
|
||||
ErrorsNative.INVALID_REFINES_IN_SWIFT_TARGETS,
|
||||
"@RefinesInSwift annotation is only applicable to annotations with targets FUNCTION and/or PROPERTY"
|
||||
)
|
||||
put(
|
||||
ErrorsNative.SUBTYPE_OF_HIDDEN_FROM_OBJC,
|
||||
"Only @HiddenFromObjC declaration can be a subtype of @HiddenFromObjC declaration"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,11 @@ object ErrorsNative {
|
||||
@JvmField
|
||||
val INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE = DiagnosticFactory2.create<KtElement, DeclarationDescriptor, Collection<DeclarationDescriptor>>(Severity.ERROR)
|
||||
@JvmField
|
||||
val INVALID_OBJC_REFINEMENT_TARGETS = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
||||
val INVALID_OBJC_HIDES_TARGETS = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
||||
@JvmField
|
||||
val INVALID_REFINES_IN_SWIFT_TARGETS = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
||||
@JvmField
|
||||
val SUBTYPE_OF_HIDDEN_FROM_OBJC = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
||||
|
||||
init {
|
||||
Errors.Initializer.initializeFactoryNames(ErrorsNative::class.java)
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.resolve.konan.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||
|
||||
/**
|
||||
* Check that the given class does not inherit from class or implements interface that is
|
||||
* marked as HiddenFromObjC (aka "marked with annotation that is marked as HidesFromObjC").
|
||||
*/
|
||||
object NativeHiddenFromObjCInheritanceChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (descriptor !is ClassDescriptor) return
|
||||
// Enum entries inherit from their enum class.
|
||||
if (descriptor.kind == ClassKind.ENUM_ENTRY) return
|
||||
// Non-public types do not leak to Objective-C API surface, so it is OK for them
|
||||
// to inherit from hidden types.
|
||||
if (!descriptor.visibility.isPublicAPI) return
|
||||
// No need to report anything on class that is hidden itself.
|
||||
if (checkClassIsHiddenFromObjC(descriptor)) return
|
||||
|
||||
val isSubtypeOfHiddenFromObjC = descriptor.getSuperInterfaces().any { checkClassIsHiddenFromObjC(it) } ||
|
||||
descriptor.getSuperClassNotAny()?.let { checkClassIsHiddenFromObjC(it) } == true
|
||||
if (isSubtypeOfHiddenFromObjC) {
|
||||
context.trace.report(ErrorsNative.SUBTYPE_OF_HIDDEN_FROM_OBJC.on(declaration))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkContainingClassIsHidden(currentClass: ClassDescriptor): Boolean {
|
||||
return (currentClass.containingDeclaration as? ClassDescriptor)?.let {
|
||||
if (checkClassIsHiddenFromObjC(it)) {
|
||||
true
|
||||
} else {
|
||||
checkContainingClassIsHidden(it)
|
||||
}
|
||||
} ?: false
|
||||
}
|
||||
|
||||
private fun checkClassIsHiddenFromObjC(clazz: ClassDescriptor): Boolean {
|
||||
clazz.annotations.forEach { annotation ->
|
||||
val objcExportMetaAnnotations = annotation.annotationClass?.findObjCExportMetaAnnotations()
|
||||
?: return@forEach
|
||||
if (objcExportMetaAnnotations.hidesFromObjCAnnotation != null) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// If outer class is hidden then inner/nested class is hidden as well.
|
||||
return checkContainingClassIsHidden(clazz)
|
||||
}
|
||||
+32
-27
@@ -12,51 +12,56 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCRefinementChecker.hidesFromObjCFqName
|
||||
import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCRefinementChecker.refinesInSwiftFqName
|
||||
|
||||
internal data class ObjCExportMetaAnnotations(
|
||||
val hidesFromObjCAnnotation: AnnotationDescriptor?,
|
||||
val refinesInSwiftAnnotation: AnnotationDescriptor?,
|
||||
)
|
||||
|
||||
internal fun DeclarationDescriptor.findObjCExportMetaAnnotations(): ObjCExportMetaAnnotations {
|
||||
require(this is ClassDescriptor && this.kind == ClassKind.ANNOTATION_CLASS)
|
||||
var objCAnnotation: AnnotationDescriptor? = null
|
||||
var swiftAnnotation: AnnotationDescriptor? = null
|
||||
for (annotation in annotations) {
|
||||
when (annotation.fqName) {
|
||||
hidesFromObjCFqName -> objCAnnotation = annotation
|
||||
refinesInSwiftFqName -> swiftAnnotation = annotation
|
||||
}
|
||||
if (objCAnnotation != null && swiftAnnotation != null) break
|
||||
}
|
||||
return ObjCExportMetaAnnotations(objCAnnotation, swiftAnnotation)
|
||||
}
|
||||
|
||||
object NativeObjCRefinementAnnotationChecker : DeclarationChecker {
|
||||
|
||||
private val supportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS)
|
||||
private val hidesFromObjCSupportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS)
|
||||
private val refinesInSwiftSupportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY)
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (descriptor !is ClassDescriptor || descriptor.kind != ClassKind.ANNOTATION_CLASS) return
|
||||
val (objCAnnotation, swiftAnnotation) = descriptor.findRefinesAnnotations()
|
||||
val (objCAnnotation, swiftAnnotation) = descriptor.findObjCExportMetaAnnotations()
|
||||
if (objCAnnotation == null && swiftAnnotation == null) return
|
||||
if (objCAnnotation != null && swiftAnnotation != null) {
|
||||
val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(swiftAnnotation) ?: declaration
|
||||
context.trace.report(ErrorsNative.REDUNDANT_SWIFT_REFINEMENT.on(reportLocation))
|
||||
}
|
||||
val targets = AnnotationChecker.applicableTargetSet(descriptor)
|
||||
val unsupportedTargets = targets - supportedTargets
|
||||
if (unsupportedTargets.isNotEmpty()) {
|
||||
objCAnnotation?.let { context.trace.reportInvalidAnnotationTargets(declaration, it) }
|
||||
swiftAnnotation?.let { context.trace.reportInvalidAnnotationTargets(declaration, it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.findRefinesAnnotations(): Pair<AnnotationDescriptor?, AnnotationDescriptor?> {
|
||||
var objCAnnotation: AnnotationDescriptor? = null
|
||||
var swiftAnnotation: AnnotationDescriptor? = null
|
||||
for (annotation in annotations) {
|
||||
when (annotation.fqName) {
|
||||
hidesFromObjCFqName -> objCAnnotation = annotation
|
||||
refinesInSwiftFqName -> swiftAnnotation = annotation
|
||||
objCAnnotation?.let {
|
||||
if ((targets - hidesFromObjCSupportedTargets).isNotEmpty()) {
|
||||
val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(it) ?: declaration
|
||||
context.trace.report(ErrorsNative.INVALID_OBJC_HIDES_TARGETS.on(reportLocation))
|
||||
}
|
||||
}
|
||||
swiftAnnotation?.let {
|
||||
if ((targets - refinesInSwiftSupportedTargets).isNotEmpty()) {
|
||||
val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(it) ?: declaration
|
||||
context.trace.report(ErrorsNative.INVALID_REFINES_IN_SWIFT_TARGETS.on(reportLocation))
|
||||
}
|
||||
if (objCAnnotation != null && swiftAnnotation != null) break
|
||||
}
|
||||
return objCAnnotation to swiftAnnotation
|
||||
}
|
||||
|
||||
private fun BindingTrace.reportInvalidAnnotationTargets(
|
||||
declaration: KtDeclaration,
|
||||
annotation: AnnotationDescriptor
|
||||
) {
|
||||
val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: declaration
|
||||
report(ErrorsNative.INVALID_OBJC_REFINEMENT_TARGETS.on(reportLocation))
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ object NativePlatformConfigurator : PlatformConfiguratorBase(
|
||||
NativeTopLevelSingletonChecker, NativeThreadLocalChecker,
|
||||
NativeObjCNameChecker, NativeObjCNameOverridesChecker,
|
||||
NativeObjCRefinementChecker, NativeObjCRefinementAnnotationChecker,
|
||||
NativeObjCRefinementOverridesChecker
|
||||
NativeObjCRefinementOverridesChecker, NativeHiddenFromObjCInheritanceChecker
|
||||
)
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
|
||||
Reference in New Issue
Block a user